一尘不染

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

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程序并从中调用的Go代码”一节中提到


阅读 223

收藏
2020-07-02

共1个答案

一尘不染

要构建可从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

2020-07-02