在现有C项目中使用Go代码

时间:2015-08-25 23:04:50

标签: c go

自从Go 1.5问世以来,我开始重新审视如何将其整合到我现有的项目中。

项目的代码库完全用C语言编写,用于低级访问硬件和其他有趣的东西。然而,一些更高级别的东西是乏味的,我想开始用更高级别的语言编写它们(Go)

有什么方法可以从C程序调用Go代码吗?我安装了Go 1.5,其中添加了-buildmode=c-archivehttps://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程序中并从其调用”一节中提到

1 个答案:

答案 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