# CGO 的基本使用 ## Go 调用 C ### 内联编码 ```go package main /* #include int test() { return 2016; } */ import "C" import "fmt" func main() { fmt.Println(C.test()) } ``` 编译命令如下: ```bash CGO_ENABLED=1 CC=gcc go build ``` ### 静态链接 C 代码写在 .c 和 .h 独立文件中,与 Go 代码共同编译。 ```cpp /** * @file: demo.h */ #ifndef DEMO_H #define DEMO_H #include __attribute__ ((visibility("default"))) extern int32_t test003_init(int32_t i); #endif // DEMO_H ``` ```cpp /** * @file: demo.c */ #include "demo.h" int32_t test003_init(int32_t i) { return i*i; } ``` main.go 如下: ```go package main /* #cgo CFLAGS : -I./ #include "demo.h" */ import "C" import "fmt" func main() { i := C.test003_init(C.int(3)) fmt.Println(i) fmt.Println("Hi") } ``` 编译命令如下: ```bash CGO_ENABLED=1 CC=gcc go build ``` ### 动态链接 C 代码写在 .c 和 .h 独立文件中,与 Go 代码分开编译。 ```cpp /** * @file: demo.h */ #ifndef DEMO_H #define DEMO_H #include __attribute__ ((visibility("default"))) extern int32_t test003_init(int32_t i); #endif // DEMO_H ``` ```cpp /** * @file: demo.c */ #include "demo.h" int32_t test003_init(int32_t i) { return i*i; } ``` 先将 C 代码编译成共享库,编译命令如下: ```bash gcc -shared -o libdemo.so demo.c ``` main.go 如下: ```go package main /* #cgo CFLAGS : -I./ #cgo LDFLAGS: -L./ -ldemo #include "demo.h" */ import "C" import "fmt" func main() { i := C.test003_init(C.int(3)) fmt.Println(i) fmt.Println("Hi") } ``` 再编译 Go 代码: ```bash CGO_ENABLED=1 CC=gcc go build ``` ### CGO 中的类型 #### 基础类型 ```go C.char C.schar(signed char) C.uchar(unsigned char) C.short C.ushort(unsigned short) C.int C.uint(unsigned int) C.long C.ulong(unsigned long) C.longlong(long long) C.ulonglong(unsigned long long) C.float C.double nil <-> NULL ``` #### Go string 转 C string ```go func C.CString(goString string) *C.char ``` 转换为 C string 会分配一个内存,因此需要释放,文档中示例如下 ```go // #include import "C" import "unsafe" ... var cmsg *C.char = C.CString("hi") defer C.free(unsafe.Pointer(cmsg)) // do something with the C string ``` #### C string 转 Go string ```go func C.GoString(cString *C.char) string func C.GoStringN(cString *C.char, length C.int) string ``` ## C 调用 Go 参考 [Build and Use Go Packages as C Libraries](./Build_and_Use_Go_Packages_as_C_Libraries.md) ## 注意事项 1. Go 调用 C 时,CGO 的注释和 import “C” 之间不能有空行,否则出现“could not determine kind of name for C.xxxxx” 等莫名奇妙的错误。