相对而言,Go 语言还是一门非常年轻的语言。虽然发展迅猛,局限性也有——类库不是特别丰富。有些开源项目,例如 x264 ,只有 C 语言版本, Go 重写一遍也不太现实。
好在 Go 提供了调用 C 函数的机制—— cgo ,本文用一个实际例子演示如何使用 cgo 调用 C 函数。
被调用库函数
为了演示需要,虚设一个名为 callee 的函数库。函数库只提供一个名为 sayHello 的函数,接口如头文件 callee.h 所示:
|
|
sayHello 函数只是简单输出 Hello, world!
,实现见源文件 callee.c :
|
|
接下来,将上述代码编译成动态库:
|
|
这个命令将 callee.c 源码编译成 callee.o 目标文件。接下来,将目标文件转成成 libcallee.so 动态库文件:
|
|
调用方
接下来,看看如何在 Go 中调用这个动态库,代码如下:
|
|
第 4 行通过 -I
选项指定头文件搜索路径,编译器据此发现头文件 callee.h 。这里 .
表示当前目录,可以根据项目情况设置为其他目录。
第 5 行通过 -L
选项指定动态库搜索路径,编译器据此发现 libcallee.so 。接着,通过 -l
参数链接到该动态库。
第 6 行则是引入头文件,据此编译器知晓 C 函数接口。
第 8 通过 import 关键字引入一个特殊的模块 C
,之后便可访问到所用链接的 C 库函数。
第 15 行,调用 sayHello 函数。
第 7 行与 8 行之间不能留空行,不然构建失败!
最后,编译整个程序:
|
|
看到没有,成功调用 sayHello 函数并输出 Hello, world!
!
自动化构建
以上例子包含多个编译步骤,需要执行多个命令。在程序开发中,经常也是如此。 如果每次修改代码后,都需要手工执行这么多命令,那么效率和质量将深受拖累。
我们可以用更自动化的手段进行构建,以 Makefile 为例:
|
|
在源码目录准备以上 Makefile ,之后运行:
|
|
可以看到, make 命令根据 Makefile 定义自动执行编译命令并执行目标程序。
Makefile 更深入的使用方法不在本节的讨论范畴,有兴趣的童鞋自行查阅资料。
完整源码
C头文件
C源文件
Go源文件
Makefile
【小菜学Go语言】系列文章首发于公众号【小菜学编程】,敬请关注: