在现有的C项目中使用Go代码
Ever since Go 1.5 came out, I started taking another look at how I could integrate it into an existing project of mine.
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)
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.
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)
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?
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"
自从Go 1.5发布以来,我开始着眼于如何将其集成到我现有的项目中 p>
该项目的代码库完全使用C语言编写,可用于低级访问硬件和其他有趣的东西。 但是,有些高级的东西很乏味,我想开始用高级语言(Go)编写它们。 p>
有什么方法可以从C调用Go代码? 程序? 我安装了Go 1.5,它添加了 但是,我似乎无法让Go生成适当的头文件来实际编译我的项目。 生成归档文件时,我在导出的符号中看到了该函数(使用objdump),但是没有包含gcc的头文件,抱怨该函数不存在(按预期) p>
I' 对Go语言来说,这是很陌生的-但是,我喜欢这种语言,并且想利用它。 是否有任何惯用的方式(我在Go的世界中经常使用“惯用的” ...)来使它们相互配合? p>
我问这个的原因 问题并特别提到的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代码”一节中提到 p>
div> -buildmode = c-archive code>( https://golang.org/s/execmodes )。 p>
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:
- 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.
I can compile it as a C callable static library with the following command:
go build -buildmode=c-archive foo.go
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);
...
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
The -pthread
option is needed because the Go runtime makes use of threads. When I run the resulting executable it prints 42
.