这篇文章主要为大家展示了“golang中cgo的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“golang中cgo的示例分析”这篇文章吧。GO调C基本原理CGO是实现Go与C互操作的方式,包括Go调C和C调Go两个过程。其中Go调C的过程比较简单。对于一个在C中定义的函数add3,在Go中调用时需要显式的使用C.add3调用。其中C是在程序中引入的一个伪包代码中的import “C”即为在Go中使用的伪包。这个包并不真实存在,也不会被Go的compile组件见到,它会在编译前被CGO工具捕捉到,并做一些代码的改写和桩文件的生成。CGO 提供了 golang 和 C 语言相互调用的机制。某些第三方库可能只有 C/C++ 的实现,完全用纯 golang 的实现可能工程浩大,这时候 CGO 就派上用场了。可以通 CGO 在 golang 在调用 C 的接口,C++ 的接口可以用 C 包装一下提供给 golang 调用。被调用的 C 代码可以直接以源代码形式提供或者打包静态库或动态库在编译时链接。推荐使用静态库的方式,这样方便代码隔离,编译的二进制也没有动态库依赖方便发布也符合 golang 的哲学。基本数值类型golang 的基本数值类型内存模型和 C 语言一样,就是连续的几个字节(1 / 2 / 4 / 8 字节)。因此传递数值类型时可以直接将 golang 的基本数值类型转换成对应的 CGO 类型然后传递给 C 函数调用,反之亦然:package main/*#include static int32_t add(int32_t a, int32_t b) { return a + b;}*/import “C”import “fmt”func main() { var a, b int32 = 1, 2 var c int32 = int32(C.add(C.int32_t(a), C.int32_t(b))) fmt.Println(c) // 3}golang 和 C 的基本数值类型转换对照表如下:C语言类型 CGO类型 Go语言类型char C.char bytesinged char C.schar int8unsigned char C.uchar uint8short C.short int16unsigned short C.ushort uint16int C.int int32unsigned int C.uint uint32long C.long int32unsigned long C.ulong uint32long long int C.longlong int64unsigned long long int C.ulonglong uint64float C.float float32double C.double float64size_t C.size_t uint注意 C 中的整形比如 int 在标准中是没有定义具体字长的,但一般默认认为是 4 字节,对应 CGO 类型中 C.int 则明确定义了字长是 4 ,但 golang 中的 int 字长则是 8 ,因此对应的 golang 类型不是 int 而是 int32 。为了避免误用,C 代码最好使用 C99 标准的数值类型golang 中切片用起来有点像 C 中的数组,但实际的内存模型还是有点区别的。C 中的数组就是一段连续的内存,数组的值实际上就是这段内存的首地址。golang 切片的内存模型如下所示(参考源码 $GOROOT/src/runtime/chan.goarray len cap | vdata由于底层内存模型的差异,不能直接将 golang 切片的指针传给 C 函数调用,而是需要将存储切片数据的内部缓冲区的首地址及切片长度取出传传递:package main/*#include static void fill_255(char* buf, int32_t len) { int32_t i; for (i = 0; i
buf[i] = 255; }}*/import “C”import ( “fmt” “unsafe”)func main() { b := make([]byte, 5) fmt.Println(b) // [0 0 0 0 0] C.fill_255((*C.char)(unsafe.Pointer(&b[0])), C.int32_t(len(b))) fmt.Println(b) // [255 255 255 255 255]}字符串golang 的字符串和 C 中的字符串在底层的内存模型也是不一样的:golang 字串符串并没有用 ‘