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

dre*_*ool 36 c go

自从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代码链接到非Go程序并从中调用"一节中提到

Jam*_*dge 57

要构建可从C调用的存档,您需要将它们标记为导出的CGo符号.
例如,如果我创建一个foo.go包含以下内容的文件:

package main

import (
    "C"
    "fmt"
)

//export PrintInt
func PrintInt(x int) {
    fmt.Println(x)
}

func main() {}
Run Code Online (Sandbox Code Playgroud)

需要注意的重要事项是:

  • 需要调用包 main
  • 你需要有一个main功能,虽然它可以是空的.
  • 您需要导入包 C
  • 您需要特殊//export注释来标记您想要从C调用的函数.

我可以使用以下命令将其编译为C可调用静态库:

go build -buildmode=c-archive foo.go
Run Code Online (Sandbox Code Playgroud)

结果将是归档foo.a和标题foo.h.在标题中,我们得到以下内容(忽略不相关的部分):

...
typedef long long GoInt64;
...
typedef GoInt64 GoInt;
...
extern void PrintInt(GoInt p0);
...
Run Code Online (Sandbox Code Playgroud)

这足以调用导出的函数.我们可以编写一个简单的C程序来调用它:

#include "foo.h"

int main(int argc, char **argv) {
    PrintInt(42);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我们可以使用如下命令编译它:

gcc -pthread foo.c foo.a -o foo
Run Code Online (Sandbox Code Playgroud)

-pthread需要该选项,因为Go运行时使用线程.当我运行生成的可执行文件它打印42.