自从Go 1.5问世以来,我开始重新审视如何将其整合到我现有的项目中。
项目的代码库完全用C语言编写,用于低级访问硬件和其他有趣的东西。然而,一些更高级别的东西是乏味的,我想开始用更高级别的语言编写它们(Go)
有什么方法可以从C程序调用Go代码吗?我安装了Go 1.5,其中添加了-buildmode=c-archive
(https://golang.org/s/execmodes),我正在努力工作。
但是,我似乎无法让Go生成适当的头文件以允许我的项目实际编译。当我生成存档时,我在导出的符号中看到了该函数(使用objdump),但没有包含gcc的头文件抱怨函数不存在(如预期的那样)
我是Go的新手 - 然而,我喜欢这种语言,并且想要使用它。是否有任何惯用的方式(“惯用”在Go的世界中被广泛使用,我看到......)让它与对方很好地玩耍?
我问这个问题并特别提到Go 1.5的原因是根据这份文件https://docs.google.com/document/d/1nr-TQHw_er6GOQRsF6T43GGhFDelrAP0NqSS_00RgZQ/edit?pli=1#heading=h.1gw5ytjfcoke Go 1.5增加了对非Go程序的支持,以调用Go代码。具体而言,在“将代码链接到非Go程序中并从其调用”一节中提到
答案 0 :(得分:51)
要构建可从C调用的存档,您需要将它们标记为导出的CGo符号
例如,如果我使用以下内容创建文件foo.go
:
package main
import (
"C"
"fmt"
)
//export PrintInt
func PrintInt(x int) {
fmt.Println(x)
}
func main() {}
需要注意的重要事项是:
main
main
函数,尽管它可以为空。C
//export
条评论来标记您希望从C调用的函数。我可以使用以下命令将其编译为C可调用静态库:
go build -buildmode=c-archive foo.go
结果将是归档foo.a
和标题foo.h
。在标题中,我们得到以下内容(忽略不相关的部分):
...
typedef long long GoInt64;
...
typedef GoInt64 GoInt;
...
extern void PrintInt(GoInt p0);
...
这足以调用导出的函数。我们可以编写一个简单的C程序来调用它:
#include "foo.h"
int main(int argc, char **argv) {
PrintInt(42);
return 0;
}
我们可以使用如下命令编译它:
gcc -pthread foo.c foo.a -o foo
需要-pthread
选项,因为Go运行时使用线程。当我运行生成的可执行文件时,它会打印42
。