Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 1 | # Introduction |
| 2 | |
| 3 | First, http://golang.org/cmd/cgo is the primary cgo documentation. |
| 4 | |
| 5 | There is also a good introduction article at http://golang.org/doc/articles/c_go_cgo.html. |
| 6 | |
| 7 | ## The basics |
| 8 | |
| 9 | If a Go source file imports ` "C" `, it is using cgo. The Go file will have access to anything appearing in the comment immediately preceding the line ` import "C" `, and will be linked against all other cgo comments in other Go files, and all C files included in the build process. |
| 10 | |
| 11 | Note that there must be no blank lines in between the cgo comment and the import statement. |
| 12 | |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 13 | To access a symbol originating from the C side, use the package name ` C `. That is, if you want to call the C function ` printf() ` from Go code, you write ` C.printf() `. Since variable argument methods like printf aren't supported yet (issue [975](https://github.com/golang/go/issues/975)), we will wrap it in the C method "myprint": |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 14 | |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 15 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 16 | package cgoexample |
| 17 | |
| 18 | /* |
| 19 | #include <stdio.h> |
| 20 | #include <stdlib.h> |
| 21 | |
| 22 | void myprint(char* s) { |
| 23 | printf("%s", s); |
| 24 | } |
| 25 | */ |
| 26 | import "C" |
| 27 | |
| 28 | import "unsafe" |
| 29 | |
| 30 | func Example() { |
| 31 | cs := C.CString("Hello from stdio\n") |
| 32 | C.myprint(cs) |
| 33 | C.free(unsafe.Pointer(cs)) |
| 34 | } |
| 35 | ``` |
| 36 | |
| 37 | ## Calling Go functions from C |
| 38 | |
| 39 | It is possible to call both top-level Go functions and function variables from C code invoked from Go code using cgo. |
| 40 | |
| 41 | ### Global functions |
| 42 | |
| 43 | Go makes its functions available to C code through use of a special ` //export ` comment. |
| 44 | Note: you can't define any C functions in preamble if you're using exports. |
| 45 | |
| 46 | For example, there are two files, foo.c and foo.go: |
| 47 | foo.go contains: |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 48 | |
| 49 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 50 | package gocallback |
| 51 | |
| 52 | import "fmt" |
| 53 | |
| 54 | /* |
| 55 | #include <stdio.h> |
| 56 | extern void ACFunction(); |
| 57 | */ |
| 58 | import "C" |
| 59 | |
| 60 | //export AGoFunction |
| 61 | func AGoFunction() { |
| 62 | fmt.Println("AGoFunction()") |
| 63 | } |
| 64 | |
| 65 | func Example() { |
| 66 | C.ACFunction() |
| 67 | } |
| 68 | ``` |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 69 | |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 70 | foo.c contains: |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 71 | |
| 72 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 73 | #include "_cgo_export.h" |
| 74 | void ACFunction() { |
| 75 | printf("ACFunction()\n"); |
| 76 | AGoFunction(); |
| 77 | } |
| 78 | ``` |
| 79 | |
| 80 | ### Function variables |
| 81 | |
| 82 | The following code shows an example of invoking a Go callback from C code. Go passes the function variable to the CGo code by calling ` CallMyFunction() `. ` CallMyFunction() ` invokes the callback by sending it back into the Go code, with the desired parameters, for unpacking and calling. |
| 83 | |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 84 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 85 | package gocallback |
| 86 | |
| 87 | import ( |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 88 | "fmt" |
Dave Day | 0d6986a | 2014-12-10 15:02:18 +1100 | [diff] [blame] | 89 | "unsafe" |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 90 | ) |
| 91 | |
| 92 | /* |
| 93 | extern void go_callback_int(void* foo, int p1); |
| 94 | |
| 95 | // normally you will have to define function or variables |
| 96 | // in another separate C file to avoid the multiple definition |
| 97 | // errors, however, using "static inline" is a nice workaround |
| 98 | // for simple functions like this one. |
| 99 | static inline void CallMyFunction(void* pfoo) { |
| 100 | go_callback_int(pfoo, 5); |
| 101 | } |
| 102 | */ |
| 103 | import "C" |
| 104 | |
| 105 | //export go_callback_int |
| 106 | func go_callback_int(pfoo unsafe.Pointer, p1 C.int) { |
| 107 | foo := *(*func(C.int))(pfoo) |
| 108 | foo(p1) |
| 109 | } |
| 110 | |
| 111 | func MyCallback(x C.int) { |
| 112 | fmt.Println("callback with", x) |
| 113 | } |
| 114 | |
| 115 | // we store it in a global variable so that the garbage collector |
| 116 | // doesn't clean up the memory for any temporary variables created. |
| 117 | var MyCallbackFunc = MyCallback |
| 118 | |
| 119 | func Example() { |
| 120 | C.CallMyFunction(unsafe.Pointer(&MyCallbackFunc)) |
| 121 | } |
| 122 | ``` |
| 123 | |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 124 | ### Function pointer callbacks |
| 125 | |
| 126 | C code can call exported Go functions with their explicit name. But if a C-program wants a function pointer, a gateway function has to be written. This is because we can't take the address of a Go function and give that to C-code since the cgo tool will generate a stub in C that should be called. The following example shows how to integrate with C code wanting a function pointer of a give type. |
| 127 | |
| 128 | Place these source files under _$GOPATH/src/ccallbacks/_. Compile and run with: |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 129 | |
| 130 | ```console |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 131 | $ gcc -c clibrary.c |
| 132 | $ ar cru libclibrary.a clibrary.o |
| 133 | $ go build ccallbacks |
| 134 | $ ./ccallbacks |
| 135 | Go.main(): calling C function with callback to us |
| 136 | C.some_c_func(): calling callback with arg = 2 |
| 137 | C.callOnMeGo_cgo(): called with arg = 2 |
| 138 | Go.callOnMeGo(): called with arg = 2 |
| 139 | C.some_c_func(): callback responded with 3 |
| 140 | ``` |
| 141 | |
| 142 | **goprog.go** |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 143 | |
| 144 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 145 | package main |
| 146 | |
| 147 | /* |
| 148 | #cgo CFLAGS: -I . |
| 149 | #cgo LDFLAGS: -L . -lclibrary |
| 150 | |
| 151 | #include "clibrary.h" |
| 152 | |
| 153 | int callOnMeGo_cgo(int in); // Forward declaration. |
| 154 | */ |
| 155 | import "C" |
| 156 | |
| 157 | import ( |
| 158 | "fmt" |
| 159 | "unsafe" |
| 160 | ) |
| 161 | |
| 162 | //export callOnMeGo |
| 163 | func callOnMeGo(in int) int { |
| 164 | fmt.Printf("Go.callOnMeGo(): called with arg = %d\n", in) |
| 165 | return in + 1 |
| 166 | } |
| 167 | |
| 168 | func main() { |
| 169 | fmt.Printf("Go.main(): calling C function with callback to us\n") |
| 170 | C.some_c_func((C.callback_fcn)(unsafe.Pointer(C.callOnMeGo_cgo))) |
| 171 | } |
| 172 | ``` |
| 173 | |
| 174 | **cfuncs.go** |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 175 | |
| 176 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 177 | package main |
| 178 | |
| 179 | /* |
| 180 | |
| 181 | #include <stdio.h> |
| 182 | |
| 183 | // The gateway function |
| 184 | int callOnMeGo_cgo(int in) |
| 185 | { |
| 186 | printf("C.callOnMeGo_cgo(): called with arg = %d\n", in); |
| 187 | return callOnMeGo(in); |
| 188 | } |
| 189 | */ |
| 190 | import "C" |
| 191 | ``` |
| 192 | |
| 193 | **clibrary.h** |
| 194 | ``` |
| 195 | #ifndef CLIBRARY_H |
| 196 | #define CLIBRARY_H |
| 197 | typedef int (*callback_fcn)(int); |
| 198 | void some_c_func(callback_fcn); |
| 199 | #endif |
| 200 | ``` |
| 201 | |
| 202 | **clibrary.c** |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 203 | |
| 204 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 205 | #include <stdio.h> |
| 206 | |
| 207 | #include "clibrary.h" |
| 208 | |
| 209 | void some_c_func(callback_fcn callback) |
| 210 | { |
| 211 | int arg = 2; |
| 212 | printf("C.some_c_func(): calling callback with arg = %d\n", arg); |
| 213 | int response = callback(2); |
| 214 | printf("C.some_c_func(): callback responded with %d\n", response); |
| 215 | } |
| 216 | ``` |
| 217 | |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 218 | ## Go strings and C strings |
| 219 | |
| 220 | Go strings and C strings are different. Go strings are the combination of a length and a pointer to the first character in the string. C strings are just the pointer to the first character, and are terminated by the first instance of the null character, ` '\0' `. |
| 221 | |
| 222 | Go provides means to go from one to another in the form of the following three functions: |
| 223 | * ` func C.CString(goString string) *C.char ` |
| 224 | * ` func C.GoString(cString *C.char) string ` |
| 225 | * ` func C.GoStringN(cString *C.char, length C.int) string ` |
| 226 | |
| 227 | One important thing to remember is that ` C.CString() ` will allocate a new string of the appropriate length, and return it. That means the C string is not going to be garbage collected and it is up to **you** to free it. A standard way to do this follows. |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 228 | |
| 229 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 230 | // #include <stdlib.h> |
| 231 | import "C" |
| 232 | import "unsafe" |
| 233 | ... |
| 234 | var cmsg *C.char = C.CString("hi") |
| 235 | defer C.free(unsafe.Pointer(cmsg)) |
| 236 | // do something with the C string |
| 237 | ``` |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 238 | |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 239 | Of course, you aren't required to use ` defer ` to call ` C.free() `. You can free the C string whenever you like, but it is your responsibility to make sure it happens. |
| 240 | |
| 241 | ## Turning C arrays into Go slices |
| 242 | |
| 243 | C arrays are typically either null-terminated or have a length kept elsewhere. |
| 244 | |
| 245 | Go provides the following function to make a new Go byte slice from a C array: |
| 246 | * ` func C.GoBytes(cArray unsafe.Pointer, length C.int) []byte ` |
| 247 | |
| 248 | To create a Go slice backed by a C array (without copying the original data), one needs to acquire this length at runtime and use ` reflect.SliceHeader `. |
| 249 | |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 250 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 251 | import "C" |
| 252 | import "unsafe" |
| 253 | ... |
| 254 | var theCArray *C.YourType = C.getTheArray() |
| 255 | length := int(C.getTheArrayLength()) |
| 256 | hdr := reflect.SliceHeader{ |
| 257 | Data: uintptr(unsafe.Pointer(theCArray)), |
| 258 | Len: length, |
| 259 | Cap: length, |
| 260 | } |
| 261 | goSlice := *(*[]C.YourType)(unsafe.Pointer(&hdr)) |
| 262 | // now goSlice is a Go slice backed by the C array |
| 263 | ``` |
| 264 | |
| 265 | It is important to keep in mind that the Go garbage collector will not interact with this data, and that if it is freed from the C side of things, the behavior of any Go code using the slice is nondeterministic. |
| 266 | |
| 267 | Another simpler solution is casting the pointer to a pointer to a very big array and then |
| 268 | slice it to the length that you want (also remember to set the cap if you're using Go 1.2 |
| 269 | or later), for example (see http://play.golang.org/p/XuC0xqtAIC for a runnable example): |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 270 | |
| 271 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 272 | import "C" |
| 273 | import "unsafe" |
| 274 | ... |
| 275 | var theCArray *C.YourType = C.getTheArray() |
| 276 | length := C.getTheArrayLength() |
| 277 | slice := (*[1 << 30]C.YourType)(unsafe.Pointer(theCArray))[:length:length] |
| 278 | ``` |
| 279 | |
| 280 | ## Common Pitfalls |
| 281 | ### Struct Alignment Issues |
| 282 | As Go doesn't support packed struct (e.g., structs where maximum alignment is 1 byte), you can't |
| 283 | use packed C struct in Go. Even if you program passes compilation, it won't do what you want. |
| 284 | To use it, you have to read/write the struct as byte array/slice. |
| 285 | |
| 286 | Another problem is that some types has lower alignment requirement than their counterpart in Go, |
| 287 | and if that type happens to be aligned in C but not in Go rules, that struct simply can't be represented |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 288 | in Go. An example is this ([issue 7560](https://github.com/golang/go/issues/7560)): |
| 289 | |
| 290 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 291 | struct T { |
| 292 | uint32_t pad; |
| 293 | complex float x; |
| 294 | }; |
| 295 | ``` |
| 296 | Go's complex64 has an alignment of 8-byte, where as C has only 4-byte (because C treats the |
| 297 | complex float internally as a ` struct { float real; float imag; } `, not a basic type), this T struct simply |
| 298 | doesn't have a Go representation. For this case, if you control the layout of the struct, move the |
| 299 | complex float so that it is also aligned to 8-byte is better, and if you're not willing to move it, |
| 300 | use this form will force it to align to 8-byte (and waste 4-byte): |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 301 | |
| 302 | ```go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 303 | struct T { |
| 304 | uint32_t pad; |
| 305 | __attribute__((align(8))) complex float x; |
| 306 | }; |
| 307 | ``` |
nathany | 86c47cc | 2014-12-10 09:43:20 -0800 | [diff] [blame^] | 308 | |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 309 | However, if you don't control the struct layout, you will have to define accessor C functions for |
| 310 | that struct because cgo won't be able to translate that struct into equivalent Go struct. |
| 311 | |
| 312 | ### ` //export ` and definition in preamble |
| 313 | If a Go source file uses any ` //export ` directives, then the C code in the comment may only include declarations (` extern int f(); `), not definitions (` int f() { return 1; } ` or ` int n; `). |
| 314 | Note: you can use ` static inline ` trick to work around this restriction for tiny functions defined |
| 315 | in the preamble (see above for a complete example). |
| 316 | |
| 317 | ### Windows |
| 318 | |
| 319 | In order to use cgo on Windows, you'll also need to first install a gcc compiler (for instance, mingw-w64) and have gcc.exe (etc.) in your PATH environment variable before compiling with cgo will work. |