blob: 97f5f9ab1eda9a8f172a9d2859cc1d92a77ffd44 [file] [log] [blame] [view]
Andrew Gerrand5bc444d2014-12-10 11:35:11 +11001# Introduction
2
3First, http://golang.org/cmd/cgo is the primary cgo documentation.
4
5There is also a good introduction article at http://golang.org/doc/articles/c_go_cgo.html.
6
7## The basics
8
9If 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
11Note that there must be no blank lines in between the cgo comment and the import statement.
12
nathany86c47cc2014-12-10 09:43:20 -080013To 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 Gerrand5bc444d2014-12-10 11:35:11 +110014
nathany86c47cc2014-12-10 09:43:20 -080015```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110016package cgoexample
17
18/*
19#include <stdio.h>
20#include <stdlib.h>
21
22void myprint(char* s) {
Jxck9f1e2a02016-05-09 14:40:47 +090023 printf("%s\n", s);
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110024}
25*/
26import "C"
27
28import "unsafe"
29
30func 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
39It 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
43Go makes its functions available to C code through use of a special ` //export ` comment.
44Note: you can't define any C functions in preamble if you're using exports.
45
46For example, there are two files, foo.c and foo.go:
47foo.go contains:
nathany86c47cc2014-12-10 09:43:20 -080048
49```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110050package gocallback
51
52import "fmt"
53
54/*
55#include <stdio.h>
56extern void ACFunction();
57*/
58import "C"
59
60//export AGoFunction
61func AGoFunction() {
62 fmt.Println("AGoFunction()")
63}
64
65func Example() {
66 C.ACFunction()
67}
68```
nathany86c47cc2014-12-10 09:43:20 -080069
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110070foo.c contains:
nathany86c47cc2014-12-10 09:43:20 -080071
72```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110073#include "_cgo_export.h"
74void ACFunction() {
75 printf("ACFunction()\n");
76 AGoFunction();
77}
78```
79
80### Function variables
81
Ian Lance Taylor19c29872016-06-02 12:14:05 -070082The following code shows an example of invoking a Go callback from C code. Because of the [pointer passing rules](https://golang.org/cmd/cgo/#hdr-Passing_pointers) Go code can not pass a function value directly to C. Instead it is necessary to use an indirection. This example uses a registry with a mutex, but there are many other ways to map from a value that can be passed to C to a Go function.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110083
nathany86c47cc2014-12-10 09:43:20 -080084```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110085package gocallback
86
87import (
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110088 "fmt"
Ian Lance Taylor19c29872016-06-02 12:14:05 -070089 "sync"
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110090)
91
92/*
Ian Lance Taylor19c29872016-06-02 12:14:05 -070093extern void go_callback_int(int foo, int p1);
Andrew Gerrand5bc444d2014-12-10 11:35:11 +110094
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.
Ian Lance Taylor19c29872016-06-02 12:14:05 -070099static inline void CallMyFunction(int foo) {
100 go_callback_int(foo, 5);
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100101}
102*/
103import "C"
104
105//export go_callback_int
Ian Lance Taylor19c29872016-06-02 12:14:05 -0700106func go_callback_int(foo C.int, p1 C.int) {
107 fn := lookup(int(foo))
108 fn(p1)
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100109}
110
111func MyCallback(x C.int) {
112 fmt.Println("callback with", x)
113}
114
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100115func Example() {
Ian Lance Taylor19c29872016-06-02 12:14:05 -0700116 i := register(MyCallback)
117 C.CallMyFunction(C.int(i))
118 unregister(i)
119}
120
121var mu sync.Mutex
122var index int
123var fns = make(map[int]func(C.int))
124
125func register(fn func(C.int)) int {
126 mu.Lock()
127 defer mu.Unlock()
128 index++
Ian Lance Taylor0a404a12016-06-03 11:03:43 -0700129 for fns[index] != nil {
130 index++
131 }
Ian Lance Taylor19c29872016-06-02 12:14:05 -0700132 fns[index] = fn
133 return index
134}
135
136func lookup(i int) func(C.int) {
137 mu.Lock()
138 defer mu.Unlock()
139 return fns[i]
140}
141
142func unregister(i int) {
143 mu.Lock()
144 defer mu.Unlock()
145 delete(fns, i)
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100146}
147```
148
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100149### Function pointer callbacks
150
151C 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.
152
153Place these source files under _$GOPATH/src/ccallbacks/_. Compile and run with:
nathany86c47cc2014-12-10 09:43:20 -0800154
155```console
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100156$ gcc -c clibrary.c
157$ ar cru libclibrary.a clibrary.o
Erwin Driessens61a22ba2015-09-14 01:05:39 +0200158$ go build
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100159$ ./ccallbacks
160Go.main(): calling C function with callback to us
161C.some_c_func(): calling callback with arg = 2
162C.callOnMeGo_cgo(): called with arg = 2
163Go.callOnMeGo(): called with arg = 2
164C.some_c_func(): callback responded with 3
165```
166
167**goprog.go**
nathany86c47cc2014-12-10 09:43:20 -0800168
169```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100170package main
171
172/*
173#cgo CFLAGS: -I .
174#cgo LDFLAGS: -L . -lclibrary
175
176#include "clibrary.h"
177
178int callOnMeGo_cgo(int in); // Forward declaration.
179*/
180import "C"
181
182import (
183 "fmt"
184 "unsafe"
185)
186
187//export callOnMeGo
188func callOnMeGo(in int) int {
189 fmt.Printf("Go.callOnMeGo(): called with arg = %d\n", in)
190 return in + 1
191}
192
193func main() {
194 fmt.Printf("Go.main(): calling C function with callback to us\n")
195 C.some_c_func((C.callback_fcn)(unsafe.Pointer(C.callOnMeGo_cgo)))
196}
197```
198
199**cfuncs.go**
nathany86c47cc2014-12-10 09:43:20 -0800200
201```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100202package main
203
204/*
205
206#include <stdio.h>
207
208// The gateway function
209int callOnMeGo_cgo(int in)
210{
211 printf("C.callOnMeGo_cgo(): called with arg = %d\n", in);
Jaana Burcu Dogan69b7bf52016-07-29 13:55:27 -0700212 int callOnMeGo(int);
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100213 return callOnMeGo(in);
214}
215*/
216import "C"
217```
218
219**clibrary.h**
emersionc05f1242018-07-07 22:38:42 +0100220
221```c
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100222#ifndef CLIBRARY_H
223#define CLIBRARY_H
224typedef int (*callback_fcn)(int);
225void some_c_func(callback_fcn);
226#endif
227```
228
229**clibrary.c**
nathany86c47cc2014-12-10 09:43:20 -0800230
emersionc05f1242018-07-07 22:38:42 +0100231```c
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100232#include <stdio.h>
233
234#include "clibrary.h"
235
236void some_c_func(callback_fcn callback)
237{
238 int arg = 2;
239 printf("C.some_c_func(): calling callback with arg = %d\n", arg);
240 int response = callback(2);
241 printf("C.some_c_func(): callback responded with %d\n", response);
242}
243```
244
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100245## Go strings and C strings
246
247Go 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' `.
248
249Go provides means to go from one to another in the form of the following three functions:
250 * ` func C.CString(goString string) *C.char `
251 * ` func C.GoString(cString *C.char) string `
252 * ` func C.GoStringN(cString *C.char, length C.int) string `
253
254One 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.
nathany86c47cc2014-12-10 09:43:20 -0800255
256```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100257// #include <stdlib.h>
258import "C"
259import "unsafe"
260...
261 var cmsg *C.char = C.CString("hi")
262 defer C.free(unsafe.Pointer(cmsg))
263 // do something with the C string
264```
nathany86c47cc2014-12-10 09:43:20 -0800265
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100266Of 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.
267
268## Turning C arrays into Go slices
269
270C arrays are typically either null-terminated or have a length kept elsewhere.
271
272Go provides the following function to make a new Go byte slice from a C array:
273 * ` func C.GoBytes(cArray unsafe.Pointer, length C.int) []byte `
274
Ian Lance Tayloreaa92d72015-12-04 14:41:43 -0800275To create a Go slice backed by a C array (without copying the original data), one needs to acquire this length at runtime and use a type conversion to a pointer to a very big array and then slice it to the length that you want (also remember to set the cap if you're using Go 1.2 or later), for example (see http://play.golang.org/p/XuC0xqtAIC for a runnable example):
nathany86c47cc2014-12-10 09:43:20 -0800276
277```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100278import "C"
279import "unsafe"
280...
281 var theCArray *C.YourType = C.getTheArray()
282 length := C.getTheArrayLength()
Ayke036c78a2019-01-22 20:01:03 +0100283 slice := (*[1 << 28]C.YourType)(unsafe.Pointer(theCArray))[:length:length]
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100284```
285
Ian Lance Tayloreaa92d72015-12-04 14:41:43 -0800286It 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.
287
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100288## Common Pitfalls
289### Struct Alignment Issues
290As Go doesn't support packed struct (e.g., structs where maximum alignment is 1 byte), you can't
Harrison Thorne4999ed82019-03-12 16:29:44 -0600291use packed C struct in Go. Even if your program passes compilation, it won't do what you want.
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100292To use it, you have to read/write the struct as byte array/slice.
293
294Another problem is that some types has lower alignment requirement than their counterpart in Go,
295and if that type happens to be aligned in C but not in Go rules, that struct simply can't be represented
nathany86c47cc2014-12-10 09:43:20 -0800296in Go. An example is this ([issue 7560](https://github.com/golang/go/issues/7560)):
297
298```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100299struct T {
300 uint32_t pad;
301 complex float x;
302};
303```
304Go's complex64 has an alignment of 8-byte, where as C has only 4-byte (because C treats the
305complex float internally as a ` struct { float real; float imag; } `, not a basic type), this T struct simply
306doesn't have a Go representation. For this case, if you control the layout of the struct, move the
307complex float so that it is also aligned to 8-byte is better, and if you're not willing to move it,
308use this form will force it to align to 8-byte (and waste 4-byte):
nathany86c47cc2014-12-10 09:43:20 -0800309
310```go
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100311struct T {
312 uint32_t pad;
313 __attribute__((align(8))) complex float x;
314};
315```
nathany86c47cc2014-12-10 09:43:20 -0800316
Andrew Gerrand5bc444d2014-12-10 11:35:11 +1100317However, if you don't control the struct layout, you will have to define accessor C functions for
318that struct because cgo won't be able to translate that struct into equivalent Go struct.
319
320### ` //export ` and definition in preamble
321If 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; `).
322Note: you can use ` static inline ` trick to work around this restriction for tiny functions defined
323in the preamble (see above for a complete example).
324
325### Windows
326
William Cotton35515bc2018-10-12 00:52:37 +0200327In 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.
328
329### environmental variables
William Cottona1263522018-10-12 01:17:06 +0200330Go os.Getenv() doesn't see variables set by C.setenv()
331
William Cotton35515bc2018-10-12 00:52:37 +0200332
333### tests
334_test.go files can't use cgo.