为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
catspeake 2021-11-01 16:42:34
自从 Go 1.5 出来后,我开始重新审视如何将它集成到我现有的项目中。该项目的代码库完全用 C 编写,用于对硬件和其他有趣的东西进行低级访问。但是,一些更高层次的东西很乏味,我想开始用更高层次的语言(Go)编写它们有什么办法可以从 C 程序中调用 Go 代码吗?我安装了 Go 1.5,它添加了-buildmode=c-archive(https://golang.org/s/execmodes),我正在尝试开始工作。但是,我似乎无法让 Go 生成适当的头文件以允许我的项目实际编译。当我生成存档时,我在导出的符号中看到了该函数(使用 objdump),但没有包含 gcc 的头文件会抱怨该函数不存在(如预期的那样)我对 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 程序并从中调用”一节中提到
查看完整描述

1 回答

?
慕婉清6462132

TA贡献1804条经验 获得超2个赞

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


查看完整回答
反对 回复 2021-11-01
  • 1 回答
  • 0 关注
  • 118 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信