forked from AlekSi/cgo-by-example
-
Notifications
You must be signed in to change notification settings - Fork 4
/
main.go
82 lines (66 loc) · 2.05 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package main
/*
#include "lib/lib.h"
#include <stdlib.h> // for free()
#cgo LDFLAGS: -L. -llib
// simple wrapper, see below
void call_f5_with_f1(void) {
f5(f1);
}
*/
import "C"
import (
"fmt"
"unsafe"
)
func F(i C.int) {
fmt.Println("Go F()")
}
func main() {
// Simple C function call.
C.f0()
// Call with constant.
C.f1(5)
// Call with Go int - cast to C int.
var i int = 8
C.f1(C.int(i))
// Convert Go string to C string (char*) and back.
cs := C.CString("Go string")
csRet := C.f2(cs)
fmt.Printf("fmt: %s\n", C.GoString(csRet))
C.free(unsafe.Pointer(cs)) // free memory right now ...
defer C.free(unsafe.Pointer(csRet)) // ... or later
// Pass C struct to C function by value.
s1 := C.struct_s1{a: 5} // or cast with C.int: s1 := C.struct_s1{C.int(i)}
s1Ret := C.f31(s1)
fmt.Printf("f31: s1=%v, s1Ret=%v\n", s1, s1Ret)
// Pass C struct to C function by pointer.
s1 = C.struct_s1{a: 5}
s1Ret = *C.f32(&s1)
fmt.Printf("f32: s1=%v, s1Ret=%v\n", s1, s1Ret)
// Pass C struct with int pointer to C function.
// s2 := C.struct_s2{&C.int(i)} - compile error "cannot take the address of _Ctype_int(i)", create variable as below
ci := C.int(i)
s2 := C.struct_s2{p: &ci}
fmt.Printf("s2=%v, *s2.p=%d, i=%d\n", s2, *s2.p, i)
C.f4(s2)
fmt.Printf("f4: s2=%v, *s2.p=%d, i=%d\n", s2, *s2.p, i)
// Pass C function pointer to C function.
// C.f5(C.f1) - compile error "must call C.f1"
// fp := unsafe.Pointer(C.f1) - compile error "must call C.f1"
// It is not possible to pass C function pointer via Go.
// Pass C function pointer to C function with simple C wrapper (see top of this file).
C.call_f5_with_f1()
// Pass Go function pointer to C function.
f := func(i C.int) {
fmt.Println("Go f()")
}
fp := unsafe.Pointer(&f)
// C.f5((*[0]byte)(fp)) - Compiles but explodes. Do not do this!
// Pass global Go function pointer to C function.
f = F
fp = unsafe.Pointer(&f)
// C.f5((*[0]byte)(fp)) - Compiles but explodes. Do not do this!
// It is possible to call Go function from C. See main2.go for solution.
_ = fp
}