[英]Using Go code in an existing C project
自从 Go 1.5 出来后,我开始重新审视如何将它集成到我现有的项目中。
该项目的代码库完全用 C 编写,用于对硬件和其他有趣内容的低级别访问。 然而,一些更高级的东西很乏味,我想开始用更高级的语言(Go)来写它们
有什么办法可以从 C 程序中调用 Go 代码吗? 我安装了 Go 1.5,其中添加了-buildmode=c-archive
( https://golang.org/s/execmodes ),我正试图开始工作。
但是,我似乎无法获得 Go 来生成适当的 header 文件以允许我的项目实际编译。 当我生成存档时,我在导出的符号中看到 function(使用 objdump),但没有 header 文件包含 gcc 抱怨 function 不存在(如预期的那样)
我是 Go 的新手 - 但是,我喜欢这种语言并想使用它。 有没有什么惯用的方法(“惯用的”在我看到的 Go 的世界中被大量使用......)让这个相互配合得很好?
我问这个问题并特别提到 Go 1.5 的原因是,根据本文档, https://docs.google.com/document/d/1nr-TQHw_er6GOQRsF6T43GGhFDelrAP0NqSS_00RgZQ/edit?pli=1#heading=h.1gw5y164088 1681 881支持非Go程序调用Go代码。 具体来说,在“Go code linked into, and called from, a non-Go program”一节中提到
要构建可从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
。
上面的代码工作得很好,但是 gcc 会抱怨函数和头文件。
包括应该是:
#define _GNU_SOURCE
#include <stdio.h>
#include "mygopkg.h"
如果您忘记了#define _GNU_SOURCE , gcc 会抱怨:
warning: implicit declaration of function 'asprintf'; did you mean 'vsprintf'? [-Wimplicit-function-declaration]
如果你忘记了#include "mygopkg.h" , gcc 会报错:
warning: implicit declaration of function 'PrintString' [-Wimplicit-function-declaration]
最后一点但同样重要。 我为生产代码推荐的构建命令行是:
go build -ldflags "-s -w" -buildmode c-archive -o mygopkg.a
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.