go 里面的 cgo 包可以直接调用 c 代码,只需要遵守一定的使用规则即可,对于那些熟悉 c/c++ 的开发者来说,不失为一个福音。
三个代表
cgo 会从 go 代码中去寻找 c/c++ 代码,约定:
紧挨在上面的所有 c 风格的注释语句都可以被 go 编译。
1.所有代码都写在一个 go 文件中
这是最简便的方式,适用于 c 代码逻辑比较简单的情况。
2.c 代码和 go 代码写在独立文件
像这种直接编译 c 源码和 go 源码的方式,只需执行,cgo 会在当前目录或 c 语言 编译参数指定的目录寻找需要的
,文件。
3.go 代码调用动态链接库
如果只提供了 c 的动态链接库和头文件,那么需要在 go 文件中指定 cgo 的 等编译选项:
go 引用 c
C 里面的标准类型可以在 go 里面直接引用:
引用 struct,union,enum:
Go 里面的 struct 不能包含 C 类型。
sizeof:
c 中结构体字段如果是 go 里面的关键字,那么可以在该结构体字段名前面加个 来引用,比如:
Cgo 将 C 类型转译成对应的 go 类型是不可导出的,因此,go 包导出的 API 里面不能含有 C 类型。
C 里面的函数执行结果可以赋给 go 里面的多返回值(执行结果和可能产生的错误值),即使是没有返回值的 类型函数。
cgo 目前还不支持直接调用 C 里面的函数指针,你可以声明一个包含 C 函数指针的 go 变量(如下的 ),这样就可以在 go 和 C 之间传递了。
在 C 里面, 如果一个函数接受一个数组参数,只需要传递数组名即可,但在 go 里面不行,你必须显示指定数组首元素的地址:
下面是几组 c 和 go 之间拷贝数据的语法:
c 引用 go
使用 导出 Go 代码
在 C 代码里面使用 关键字引用 go 代码
传递指针
go 是一门垃圾回收语言,垃圾回收器需要知道每个指针所指向的内存位置,正因为如此,在 go 和 c 之间传递指针有些许限制。
go 指针:使用 操作符或 函数返回的指针
c 指针: 使用 返回的指针
首先,我们需要明白:
将指针传递给 struct 某个字段时,所涉及的 Go 内存是该字段占用的内存,而不是整个结构体占有的内存;将指针传递给数组或切片中的元素时,所涉及的 Go 内存是整个数组或整个切片的底层数组。
go 代码可以传递 go 指针给 c, 前提是这个指针指向的内存不包含任何 go 指针。c 代码必须保留这个属性:
它不能在 go 内存中存储任何 go 指针(即使是临时变量也不行)。
C 代码调用的 Go 函数可能会将 C 指针作为参数,并且可能通过这些指针存储非指针或 C 指针数据,但是它可能不会将 Go 指针存储在由C 指针指向的内存中;C 代码调用的 Go 函数可能会将 Go 指针作为参数,但它必须保留“指向的 Go 内存不包含任何 Go 指针”的属性。
Go 代码可能不会在 C 内存中存储 Go 指针,C 代码可能会在 C 内存中存储 Go 指针,这取决于上面的规则:当 C 函数返回时,它必须停止存储 Go 指针。
References
https://blog.golang.org/c-go-cgo
https://golang.org/cmd/cgo/
领取专属 10元无门槛券
私享最新 技术干货