自从Go 1.5发布以来,我开始着眼于如何将其集成到我现有的项目中。
该项目的代码库完全用C编写,可以低级访问硬件和其他有趣的东西。但是,某些较高层次的东西很繁琐,我想开始用较高层次的语言(Go)编写它们
我可以通过C程序调用Go代码吗?我安装了Go 1.5,它添加了-buildmode=c-archive(https://golang.org/s/execmodes),我正试图开始工作。
-buildmode=c-archive
但是,我似乎无法让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程序并从中调用的Go代码”一节中提到
要构建可从C调用的档案,您需要将其标记为导出的CGo符号。 例如,如果我创建一个foo.go具有以下内容的文件:
foo.go
package main import ( "C" "fmt" ) //export PrintInt func PrintInt(x int) { fmt.Println(x) } func main() {}
要注意的重要事项是:
main
C
//export
我可以使用以下命令将其编译为C可调用静态库:
go build -buildmode=c-archive foo.go
结果将是一个存档foo.a和一个标头foo.h。在标题中,我们得到以下内容(不相关的部分):
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。
-pthread
42