在现有 C 项目中使用 Go 代码 [英] Using Go code in an existing C project
问题描述
自从 Go 1.5 发布后,我开始重新审视如何将其集成到我现有的项目中.
Ever since Go 1.5 came out, I started taking another look at how I could integrate it into an existing project of mine.
该项目的代码库完全用 C 编写,用于对硬件和其他有趣的东西进行低级访问.但是,一些更高层次的东西很乏味,我想开始用更高层次的语言(Go)编写它们
The project's codebase is written entirely in C for low level access to to hardware and other fun stuff. However, some of the higher level things are tedious, and I would like to start writing them in a higher level language (Go)
有什么办法可以从 C 程序中调用 Go 代码?我安装了 Go 1.5,其中添加了 -buildmode=c-archive
(https://golang.org/s/execmodes) 我正在努力工作.
Is there any way I can call Go code from a C program? I installed Go 1.5, which added -buildmode=c-archive
(https://golang.org/s/execmodes) which I am trying to get working.
但是,我似乎无法让 Go 生成适当的头文件以允许我的项目实际编译.当我生成存档时,我在导出的符号中看到该函数(使用 objdump),但没有包含 gcc 的头文件会抱怨该函数不存在(如预期)
However, I can't seem to get Go to generate the appropriate header files to allow my project to actually compile. When I generate the archive, I see the function in the exported symbols (using objdump), but without the header files to include gcc complains about the function not existing (as expected)
我对 Go 还很陌生——但是,我喜欢这门语言并想使用它.有没有什么惯用的方式(惯用的"在围棋世界中被广泛使用,我看到......)来让它相互很好地发挥作用?
I'm quite new to Go - however, I love the language and would like to make use of it. Is there any idiomatic way ("idiomatic" gets used a lot in the world of Go I see...) to get this to play nicely with each other?
我问这个问题并特别提到 Go 1.5 的原因是根据这个文档,https://docs.google.com/document/d/1nr-TQHw_er6GOQRsF6T43GGhFDelrAP0NqSS_00RgZQ/edit?pli=1#heading=h.1gw5ytjfcokeGo 1.5 添加了对非 Go 程序调用 Go 代码的支持.具体来说,在Go 代码链接到非 Go 程序并从中调用"一节中提到
The reason I asked this question and specifically mentioned Go 1.5 is that according to this document, https://docs.google.com/document/d/1nr-TQHw_er6GOQRsF6T43GGhFDelrAP0NqSS_00RgZQ/edit?pli=1#heading=h.1gw5ytjfcoke Go 1.5 added support for non-Go programs to call Go code. Specifically, mentioned under the section "Go code linked into, and called from, a non-Go program"
推荐答案
要构建可从 C 调用的存档,您需要将它们标记为导出的 CGo 符号.
例如,如果我创建一个包含以下内容的文件 foo.go
:
To build an archive callable from C, you will need to mark them as exported CGo symbols.
For example, if I create a file foo.go
with the following contents:
package main
import (
"C"
"fmt"
)
//export PrintInt
func PrintInt(x int) {
fmt.Println(x)
}
func main() {}
需要注意的重要事项是:
The important things to note are:
- 需要调用包
main
- 您需要有一个
main
函数,尽管它可以为空. - 您需要导入包
C
- 您需要特殊的
//export
注释来标记您希望从 C 中调用的函数.
- The package needs to be called
main
- You need to have a
main
function, although it can be empty. - You need to import the package
C
- You need special
//export
comments to mark the functions you want callable from C.
我可以使用以下命令将其编译为 C 可调用静态库:
I can compile it as a C callable static library with the following command:
go build -buildmode=c-archive foo.go
结果将是一个存档 foo.a
和一个标题 foo.h
.在标题中,我们得到以下内容(删除不相关的部分):
The results will be an archive foo.a
and a header foo.h
. In the header, we get the following (eliding irrelevant parts):
...
typedef long long GoInt64;
...
typedef GoInt64 GoInt;
...
extern void PrintInt(GoInt p0);
...
这样就足以调用导出的函数了.我们可以编写一个简单的 C 程序来调用它:
So that's enough to call the exported function. We can write a simple C program that calls it like so:
#include "foo.h"
int main(int argc, char **argv) {
PrintInt(42);
return 0;
}
我们可以使用如下命令编译它:
We can compile it with a command like:
gcc -pthread foo.c foo.a -o foo
-pthread
选项是必需的,因为 Go 运行时使用线程.当我运行生成的可执行文件时,它会打印 42
.
The -pthread
option is needed because the Go runtime makes use of threads. When I run the resulting executable it prints 42
.
这篇关于在现有 C 项目中使用 Go 代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!