Can I define C functions that accept native Go types through CGo? - go

For the work I'm doing to integrate with an existing library, I ended up needing to write some additional C code to provide an interface that was usable through CGo.
In order to avoid redundant data copies, I would like to be able to pass some standard Go types (e.g. Go strings) to these C adapter functions.
I can see that there are GoString and GoInterface types defined in the header CGo generates for use by exported Go functions, but is there any way to use these types in my own function prototypes that CGo will recognise?
At the moment, I've ended up using void * in the C prototypes and passing unsafe.Pointer(&value) on the Go side. This is less clean than I'd like though (for one thing, it gives the C code the ability to write to the value).
Update:
Just to be clear, I do know the difference between Go's native string type and C char *. My point is that since I will be copying the string data passed into my C function anyway, it doesn't make sense to have the code on the Go side make its own copy.
I also understand that the string layout could change in a future version of Go, and its size may differ by platform. But CGo is already exposing type definitions that match the current platform to me via the documented _cgo_export.h header it generates for me, so it seems a bit odd to talk of it being unspecified:
typedef struct { char *p; int n; } GoString;
But there doesn't seem to be a way to use this definition in prototypes visible to CGo. I'm not overly worried about binary compatibility, since the code making use of this definition would be part of my Go package, so source level compatibility would be enough (and it wouldn't be that big a deal to update the package if that wasn't the case).

Not really. You cannot safely mix, for example Go strings (string) and C "strings" (*char) code without using the provided helpers for that, ie. GoString and CString. The reason is that to conform to the language specs a full copy of the string's content between the Go and C worlds must be made. Not only that, the garbage collector must know what to consider (Go strings) and what to ignore (C strings). And there are even more things to do about this, but let me keep it simple here.
Similar and/or other restrictions/problems apply to other Go "magical" types, like map or interface{} types. In the interface types case (but not only it), it's important to realize that the inner implementation of an interface{} (again not only this type), is not specified and is implementation specific.
That's not only about the possible differences between, say gc and gccgo. It also means that your code will break at any time the compiler developers decide to change some detail of the (unspecified and thus non guaranteed) implementation.
Additionally, even though Go doesn't (now) use a compacting garbage collector, it may change and without some pinning mechanism, any code accessing Go run time stuff directly will be again doomed.
Conclusion: Pass only simple entities as arguments to C functions. POD structs with simple fields are safe as well (pointer fields generally not). From the complex Go types, use the provided helpers for Go strings, they exists for a (very good) reason.

Passing a Go string to C is harder than it should be. There is no really good way to do it today. See https://golang.org/issue/6907.
The best approach I know of today is
// typedef struct { const char *p; ptrdiff_t n; } gostring;
// extern CFunc(gostring s);
import "C"
func GoFunc(s string) {
C.CFunc(*(*C.gostring)(unsafe.Pointer(&s)))
}
This of course assumes that Go representation of a string value will not change, which is not guaranteed.

Related

Why casting interface{} to cgo types is not allowed?

It's more of a technical question, not really an issue. Since we don't have variadic functions in cgo and there's currently no valid solution, I wonder if it'd be possible to cast interface{} to cgo types. So this would allow us to have more dynamic functions. I'm pretty sure we're not even allowed to assign types in a dynamic way to arguments in exported (//export) functions, neither the use of ellipsis is allowed. So what's the reason behind all those limits?
Thanks for answering.
import "C"
//export Foo
func Foo(arg1, arg2, arg3) {
}
C compilers are allowed, but not required, to return different types using different return mechanisms. For instance, some C compilers might return float results in the %f0 register, double results in the %f0:f1 register pair, integer results in the %d0 register, and pointer results in the %a0 register.
What this means for the person writing the Cgo interface for Go is that they must, in general, handle each kind of these C functions differently. In other words, it's not possible to write:
generic_type Cfunc(ctype1 arg1, ctype2 arg2) { ... }
We must know, at compile time, that Cfunc returns float/double/<some-integer-type>/<some-pointer-type> so that we can grab the correct register(s) and stuff its (or their) value(s) into the Cgo return-value slot, where the Cgo interface can get it and wrap it up for use in Go.
What this means for you, as a user of a Go compiler that implements Cgo wrappers to call C functions, is that you have to know the right type. There is no generalized answer; there is no way to use interface{} here. You must communicate the exact, correct type to the Cgo layer, so that the Cgo layer can use that exact, correct type information to generate the correct machine code at compile time.
If the C compiler writers had some way of flagging their code so that, e.g., at link time, the linker could pull in the right "save correct register to memory" location, that would enable the Cgo wrapper author to use the linker to automagically find the C function's type at link time. But these C compilers don't offer this ability to the linkers.
Is your particular compiler one of these? We don't know: you didn't say. But:
I'm pretty sure we're not even allowed to assign types in a dynamic way to arguments in exported (//export) functions, neither the use of ellipsis is allowed. So what's the reason behind all those limits?
That's correct, and the (slightly theoretical) example above is a reason. (I constructed this example by mixing actual techniques from 68k C compilers and SPARC C compilers, so I don't think there's any single C compiler like this. But examples like this did exist in the past, and SPARC systems still return integers in %o0, or %o0+%o1 on V8 SPARC, vs floating point in %f0 or %f0+%f1.)

Why go package unsafe source code only six lines?

package unsafe
type ArbitraryType int
type Pointer *ArbitraryType
func Sizeof(x ArbitraryType) uintptr
func Offsetof(x ArbitraryType) uintptr
func Alignof(x ArbitraryType) uintptr
What's the principle of Sizeof, Offsetof, Alignof?
Usually just having a function signature without an implementations means that the implementation is elsewhere. Usually in a separate assembly file.
In this case, you have stumbled upon one of two situations in the standard library where it is not implemented in assembly: unsafe and builtin.
The Go implementation of those packages are only there to provide documentation inside godoc. Their use is defined in the Go language specification and because of that are implemented in a way that would be impossible to implement in Go. In the case of unsafe, "ArbitraryType" really means that it accepts all possible types. This would normally be impossible to do without implicit interface conversion. But the functions are implemented by the compiler as they are needed and get to ignore the normal restrictions on Go code.
But what is the unsafe package? It is a package that provides various tools for doing low level work. Its main use is in doing direct syscalls or cgo. Using unsafe gives you a great amount of power but also doesn't stop you from using that power to shoot yourself in the foot. If at all possible, I recommend avoiding it.
Further reading:
https://golang.org/pkg/unsafe/
https://golang.org/ref/spec#Package_unsafe

What is the rationale of Go not having the const qualifier?

I'm a C++ senior programmer. I'm currently doing some Go programming. The only feature I really miss is the const qualifier. In go, if you want to modify an object, you pass its pointer. If you don't want to modify it, you pass it by value. But if the struct is big, you should pass it by pointer, which overrides the no-modification feature. Worse, you can pass an object by value, but if it contains a pointer, you can actually modify its contents, with terrible race condition dangers. Some language types like maps and slices have this feature. This happens in a language that's supposed to be built for concurrency. So the issue of avoiding modification is really non-existent in Go, and you should pass small objects that do not contain pointers (you must be aware that the object does not contain a pointer) by value, if they aren't gonna be modified.
With const, you can pass objects by const pointer and don't worrying about modification. Type-safety is about having a contract that allows speed and prevents type-related bugs. Another feature that does this too is the const qualifier.
The const type qualifier in C/C++ has various meanings. When applied to a variable, it means that the variable is immutable. That's a useful feature, and one that is missing from Go, but it's not the one you seem to be talking about.
You are talking about the way that const can be used as a partially enforced contract for a function. A function can give a pointer parameter the const qualifier to mean that the function won't change any values using that pointer. (Unless, of course, the function uses a cast (a const_cast in C++). Or, in C++, the pointer points to a field that is declared mutable.)
Go has a very simple type system. Many languages have a complex type system in which you enforce the correctness of your program by writing types. In many cases this means that a good deal of programming involves writing type declarations. Go takes a different approach: most of your programming involves writing code, not types. You write correct code by writing correct code, not by writing types that catch cases where you write incorrect code. If you want to catch incorrect code, you write analyzers, like go vet that look for cases that are invalid in your code. These kinds of analyzers are much much easier to write for Go than for C/C++, because the language is simpler.
There are advantages and disadvantages to this kind of approach. Go is making a clear choice here: write code, not types. It's not the right choice for everyone.
Please treat it as an expanded comment. I'm not any programming language designer, so can't go deep inside the details here, but will present my opinion as a long-term developer in C++ and short-term developer in Go.
Const is a non-trivial feature for the compiler, so one would have to make sure whether it's providing enough advantage for the user to implement it as well as won't sacrifice the simplicity of syntax. You might think it's just a const qualifier we're talking about, but looking at C++ itself, it's not so easy – there're a lot of caveats.
You say const is a contract and you shouldn't be able to modify it at any circumstances. One of your arguments against using read only interfaces is that you can cast it to original type and do whatever you want. Sure you can. The same way you can show a middle finger to the contract in C++ by using const_cast. For some reason it was added to the language and, not sure I should be proud of it, I've used it once or twice.
There's another modifier in C++ allowing you to relax the contract – mutable. Someone realised that const structures might actually need to have some fields modified, usually mutexes protecting internal variables. I guess you would need something similar in Go in order to be able to implement thread-safe structures.
When it comes simple const int x people can easily follow. But then pointers jump in and people really get consfused. const int * x, int * const x, const int * const x – these are all valid declarations of x, each with different contract. I know it's not a rocket science to choose the right one, but does your experience as a senior C++ programmer tell you people widely understand these and are always using the right one? And I haven't even mentioned things like const int * const * * * const * const x. It blows my mind.
Before I move to point 4, I would like to cite the following:
Worse, you can pass an object by value, but if it contains a pointer,
you can actually modify its contents
Now this is interesting accusation. There's the same issue in C++; worse – it exists even if you declare object as const, which means you can't solve the problem with a simple const qualifier. See the next point:
Per 3, and pointers, it's not so easy to express the very right contract and things sometimes get unexpected. This piece of code surprised a few people:
struct S {
int *x;
};
int main() {
int n = 7;
const S s = {&n}; // don't touch s, it's read only!
*s.x = 666; // wait, what? s is const! is satan involved?
}
I'm sure it's natural for you why the code above compiles. It's the pointer value you can't modify (the address it points to), not the value behind it. You must admit there're people around that would raise their eyebrow.
I don't know if it makes any point, but I've been using const in C++ all the time. Very accurate. Going mental about it. Not sure whether is has ever saved my ass, but after moving to Go I must admit I've never missed it. And having in mind all these edge cases and exceptions I can really believe creators of a minimalistic language like Go would decide to skip on this one.
Type-safety is about having a contract that allows speed and prevents
type-related bugs.
Agreed. For example, in Go, I love there're no implicit conversions between types. This is really preventing me from type-related bugs.
Another feature that does this too is the const qualifier.
Per my whole answer – I don't agree. Where a general const contract would do this for sure, a simple const qualifier is not enough. You then need a mutable one, maybe kind of a const_cast feature and still – it can leave you with misleading believes of protection, because it's hard to understand what exactly is constant.
Hopefully some language creators will design a perfect way of defining constants all over in our code and then we'll see it in Go. Or move over to the new language. But personally, I don't think C++'s way is a particularly good one.
(Alternative would be to follow functional programming paradigms, which would love to see all their "variables" immutable.)

Move Semantics in Golang

This from Bjarne Stroustrup's The C++ Programming Language, Fourth Edition 3.3.2.
We didn’t really want a copy; we just wanted to get the result out of
a function: we wanted to move a Vector rather than to copy it.
Fortunately, we can state that intent:
class Vector {
// ...
Vector(const Vector& a); // copy constructor
Vector& operator=(const Vector& a); // copy assignment
Vector(Vector&& a); // move constructor
Vector& operator=(Vector&& a); // move assignment
};
Given that definition, the compiler will choose the move constructor
to implement the transfer of the return value out of the function.
This means that r=x+y+z will involve no copying of Vectors. Instead,
Vectors are just moved.As is typical, Vector’s move constructor is
trivial to define...
I know Golang supports traditional passing by value and passing by reference using Go style pointers.
Does Go support "move semantics" the way C++11 does, as described by Stroustrup above, to avoid the useless copying back and forth? If so, is this automatic, or does it require us to do something in our code to make it happen.
Note: A few answers have been posted - I have to digest them a bit, so I haven't accepted one yet - thanks.
The breakdown is like here:
Everything in Go is passed by value.
But there are five built-in "reference types" which are passed by value as well but internally they hold references to separately maintained data structure: maps, slices, channels, strings and function values (there is no way to mutate the data the latter two reference).
Your own answer, #Vector, is incorrect is that nothing in Go is passed by reference. Rather, there are types with reference semantics. Values of them are still passed by value (sic!).
Your confusion suppsedly stems from the fact your mind is supposedly currently burdened by C++, Java etc while these things in Go are done mostly "as in C".
Take arrays and slices for instance. An array is passed by value in Go, but a slice is a packed struct containing a pointer (to an underlying array) and two platform-sized integers (the length and the capacity of the slice), and it's the value of this structure which is copied — a pointer and two integers — when it's assigned or returned etc. Should you copy a "bare" array, it would be copied literally — with all its elements.
The same applies to channels and maps. You can think of types defining channels and maps as declared something like this:
type Map struct {
impl *mapImplementation
}
type Slice struct {
impl *sliceImplementation
}
(By the way, if you know C++, you should be aware that some C++ code uses this trick to lower exposure of the details into header files.)
So when you later have
m := make(map[int]string)
you could think of it as m having the type Map and so when you later do
x := m
the value of m gets copied, but it contains just a single pointer, and so both x and m now reference the same underlying data structure. Was m copied by reference ("move semantics")? Surely not! Do values of type map and slice and channel have reference semantincs? Yes!
Note that these three types of this kind are not at all special: implementing your custom type by embedding in it a pointer to some complicated data structure is a rather common pattern.
In other words, Go allows the programmer to decide what semantics they want for their types. And Go happens to have five built-in types which have reference semantics already (while all the other built-in types have value semantics). Picking one semantics over the other does not affect the rule of copying everything by value in any way. For instance, it's fine to have pointers to values of any kind of type in Go, and assign them (so long they have compatible types) — these pointers will be copied by value.
Another angle to look at this is that many Go packages (standard and 3rd-party) prefer to work with pointers to (complex) values. One example is os.Open() (which opens a file on a filesystem) returning a value of the type *os.File. That is, it returns a pointer and expects the calling code to pass this pointer around. Surely, the Go authors might have declared os.File to be a struct containing a single pointer, essentially making this value have reference semantics but they did not do that. I think the reason for this is that there's no special syntax to work with the values of this type so there's no reason to make them work as maps, channels and slices. KISS, in other words.
Recommended reading:
"Go Data Structures"
"Go Slices: Usage and Internals"
Arrays, slices (and strings): The mechanics of 'append'"
A thead on golang-nuts — pay close attention to the reply by Rob Pike.
The Go Programming Language Specification
Calls
In a function call, the function value and arguments are evaluated in
the usual order. After they are evaluated, the parameters of the call
are passed by value to the function and the called function begins
execution. The return parameters of the function are passed by value
back to the calling function when the function returns.
In Go, everything is passed by value.
Rob Pike
In Go, everything is passed by value. Everything.
There are some types (pointers, channels, maps, slices) that have
reference-like properties, but in those cases the relevant data
structure (pointer, channel pointer, map header, slice header) holds a
pointer to an underlying, shared object (pointed-to thing, channel
descriptor, hash table, array); the data structure itself is passed by
value. Always.
Always.
-rob
It is my understanding that Go, as well as Java and C# never had the excessive copying costs of C++, but do not solve ownership transference to containers. Therefore there is still copying involved. As C++ becomes more of a value-semantics language, with references/pointers being relegated to i) smart-pointer managed objects inside classes and ii) dependence references, move semantics solves the problem of excessive copying. Note that this has nothing to do with "pass by value", nowadays everyone passes objects by Reference (&) or Const Reference (const &) in C++.
Let's look at this (1) :
BigObject BO(big,stuff,inside);
vector<BigObject> vo;
vo.reserve(1000000);
vo.push_back(BO);
Or (2)
vector<BigObject> vo;
vo.reserve(1000000);
vo.push_back(BigObject(big,stuff,inside));
Although you're passing by reference to the vector vo, in C++03 there was a copy inside the vector code.
In the second case, there is a temporary object that has to be constructed and then is copied inside the vector. Since it can only be accessed by the vector, that is a wasteful copy.
However, in the first case, our intent could be just to give control of BO to the vector itself. C++17 allows this:
(1, C++17)
vector<BigObject> vo;
vo.reserve(1000000);
vo.emplace_back(big,stuff,inside);
Or (2, C++17)
vector<BigObject> vo;
vo.reserve(1000000);
vo.push_back(BigObject(big,stuff,inside));
From what I've read, it is not clear that Java, C# or Go are exempt from the same copy duplication that C++03 suffered from in the case of containers.
The old-fashioned COW (copy-on-write) technique, also had the same problems, since the resources will be copied as soon as the object inside the vector is duplicated.
Stroustrup is talking about C++, which allows you to pass containers, etc by value - so the excessive copying becomes an issue.
In Go, (like in Delphi, Java, etc) when you pass a container type, etc they are always references, so it's a non-issue. Regardless, you don't have to deal with it or worry about in GoLang - the compiler just does what it needs to do, and from what I've seen thus far, it's doing it right.
Tnx to #KerrekSB for putting me on the right track.
#KerrekSB - I hope this is the right answer. If it's wrong, you bear no responsibility.:)

Purpose of using Windows Data Types in a program

I am trying to understand the purpose of using Windows Data Types when defining parameters of a function/structure fields in a particular language. I've read explanations detailing how this prevents code from "breaking" if "underlying types" are changed. Can some one present a concise explanation and example to clarify? Thanks.
Found answer in a similar post (Why are the standard datatypes not used in Win32 API?):
And the reason that these types are defined the way they are, rather than using int, char and so on is that it removes the "whatever the compiler thinks an int should be sized as" from the interface of the OS. Which is a very good thing, because if you use compiler A, or compiler B, or compiler C, they will all use the same types - only the library interface header file needs to do the right thing defining the types.
By defining types that are not standard types, it's easy to change int from 16 to 32 bit, for example. The first C/C++ compilers for Windows were using 16-bit integers. It was only in the mid to late 1990's that Windows got a 32-bit API, and up until that point, you were using int that was 16-bit. Imagine that you have a well-working program that uses several hundred int variables, and all of a sudden, you have to change ALL of those variables to something else... Wouldn't be very nice, right - especially as SOME of those variables DON'T need changing, because moving to a 32-bit int for some of your code won't make any difference, so no point in changing those bits.
It should be noted that WCHAR is NOT the same as const char - WCHAR is a "wide char" so wchar_t is the comparable type.
So, basically, the "define our own type" is a way to guarantee that it's possible to change the underlying compiler architecture, without having to change (much of the) source code. All larger projects that do machine-dependant coding does this sort of thing.

Resources