CGO是Go程序调用C库的一套机制,可以使Go语言能够站在C/C++的肩膀上。比如Go调用Tensorflow,也就是使用了CGO来实现的。很多语言都支持对C库的调用,一般称为FFI(Foreign Function Interface)。这里需要注意一下,一般的Python、Lua等语言调用C函数的时候,是通过函数签名找到函数的地址,然后直接调用对应的函数。而CGO会先生成中间文件,然后再一起编译调用。这里不具体展开了,总之只需要知道CGO比一般的FFI多了一层中间的步骤。在程序出错的时候,能理解调用栈的关系即可。参考 CGO 和 CGO 性能之谜。
函数调用
package main
/*
CGO的标准写法:
1. 先用注释的方式写入,单行注释和多行注释都支持
1.1 编译器环境变量
1.1.1 CFLAGS: C编译选项
1.1.2 CXXFLAGS: C++编译选项
1.1.3 CPPFLAGS: C和C++共有的编译选项
1.1.4 FFLAGS: Fortran编译选项
1.1.4 LDFLAGS: 链接选项(不区分C和C++)
1.2 C代码
2. import "C",相当于将所有的C函数放入虚拟的package C。之后通过`C.xxx`的方式来调用。需要紧跟注释之后。
*/
/*
#cgo LDFLAGS: -lm
#include <math.h>
double my_sqrt(double x) {
return sqrt(x);
}
*/
import "C" // CGO的标准写法,相当于将C函数放入包`C`中
import "fmt"
func main() {
a := 100
fmt.Printf("sqrt(%v) = %v\n", a, C.my_sqrt(C.double(a))) // 调用上面自定义的函数
fmt.Printf("sqrt(%v) = %v\n", a, C.sqrt(C.double(a))) // 调用系统库函数(上述的m)
}
// Output:
// sqrt(100) = 10
// sqrt(100) = 10
通过上述的例子,我们可以看出,CGO可以调用C的库函数,也可以执行注释中的C代码的函数。一般注释中的C代码都是比较简短的。
接下来要介绍C和Go之间的数据是如何传递的。
Read More...