自从Go 1.5问世以来,我开始重新审视如何将其整合到我现有的项目中.
该项目的代码库完全用C语言编写,用于低级访问硬件和其他有趣的东西.然而,一些更高级别的东西是乏味的,我想开始用更高级别的语言编写它们(Go)
有什么方法可以从C程序调用Go代码吗?我安装了Go 1.5,它添加了-buildmode=c-archive(https://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程序并从中调用"一节中提到
可以在Windows上调用Go函数C++或C#代码吗?Go支持在Windows中生成dll吗?
我听说Go就像C一样有渠道和很多便利.我做的很少C,但是当我这么做的时候就是对其他语言进行小扩展.Can Go是一种安全的方式来创建其他语言的扩展吗?人们这样做吗?
我有一个完全用C语言编写的程序,其中包含多个目标(.o)文件.这些文件都打包在一个存档文件(.a)中,而该存档文件又在程序主(.c)文件的编译时使用.
我想在Go中为这个项目写一个新文件.我的想法是编写这个.go文件,然后(.o)从中创建一个目标文件.之后,我想将此对象文件放在已提到的存档(.a)文件中.
这基本上意味着我想从C程序调用Go函数.我已经读过这个问题了,虽然它向我展示了我想要的东西是通过GCCGO实现的,但它并不是100%清楚如何去做.
即使使用最基本的测试,我也会在链接阶段遇到错误.更具体地说,这是一个基本的例子:
printString.go
package main
import
(
"fmt"
)
func PrintString(buff string) int {
fmt.Printf(buff)
return 1
}
Run Code Online (Sandbox Code Playgroud)
c_caller.c
#define _GNU_SOURCE
#include <stdio.h>
extern int PrintString(char*) __asm__ ("print.main.PrintString");
int main() {
char *string_to_pass= NULL;
asprintf(&string_to_pass, "This is a test.");
int result= PrintString(string_to_pass);
if(result) {printf("Everything went as expected!\n");}
else {printf("Uh oh, something went wrong!\n");}
return result;
}
Run Code Online (Sandbox Code Playgroud)
编译
为了编译Go文件,我使用了以下命令:
gccgo -c printString.go -o …Run Code Online (Sandbox Code Playgroud) 我正在编写代码以使用LLVM Go 绑定从自定义 VM 字节码生成 LLVM 字节码;然后代码被即时编译并在进程中执行。
自定义VM字节码有几个不能直接在LLVM中实现的操作,因为它们需要改变外部状态;这些操作码的功能是作为 Go 函数实现的。
有一些关于如何开始从 Go 生成 LLVM 字节码的优秀指南,但没有一个指南解决回调或导出函数的问题。是否可以生成 LLVM 指令来回调 Go 函数?如果是这样,怎么办?
我已经尝试过@arrowd 下面描述的方法,但它似乎不起作用。源代码,改编自 Felix Angell 的博文:
package main
import (
"C"
"fmt"
"llvm.org/llvm/final/bindings/go/llvm"
)
// export AddInts
func AddInts(arg1, arg2 int) int {
return arg1 + arg2;
}
func main() {
// setup our builder and module
builder := llvm.NewBuilder()
mod := llvm.NewModule("my_module")
// create our function prologue
main := llvm.FunctionType(llvm.Int32Type(), []llvm.Type{}, false)
llvm.AddFunction(mod, "main", main)
block := …Run Code Online (Sandbox Code Playgroud) 假设我有一个 C 库,代码如下:
typedef int (callback_t)(int);
void register_callback(callback_t cb);
Run Code Online (Sandbox Code Playgroud)
我想为此函数编写 go 绑定并传递任意 go 回调。
我在这里找到了一个很好的答案。然而,这是一个利用回调接受 a 的事实的技巧void *,Go 通过它将函数指针传递给 C 并接收它。但是,这不能应用于我的示例,因为没有 user void *。
我能做的最好的事情是:
/*
extern int gobridge(int data);
static int cbridge(void)
{
register_callback(gobridge);
}
*/
import "C"
type Callback func (int) int
var g_cb Callback
//export gobridge
func gobridge(data C.int) C.int {
return C.int(g_cb(int(data)))
}
func RegisterCallback(cb Callback) {
g_cb = cb //save callback in a global
C.cbridge()
}
func Count(left, right int) { …Run Code Online (Sandbox Code Playgroud) 我正在寻找这两种语言之间FFI的最小例子,这是一个非常简单的Go程序调用Fortran库的hello世界.
我想强调一点,我不是在寻找外部资源,建议或教程,只是golang中的最小代码片段,以及Fortran中的相应格式.
这个网站上有很多例子:
Go - > Fortran示例符合这些并且对其他开发人员有用.
这个问题有一个答案和一个链接的问题,因为这是一个副本而不是.关闭并重定向此问题作为可能以-5票结束的副本对stackoverflow用户没有用,尽管两者都提出了一个合理的问题.
我有一个项目,我想在C++应用程序中加载Go插件.
经过大量的研究,我不清楚Go是否支持这一点.我遇到了很多讨论指出动态链接的坏习惯,而不是IPC.此外,我不清楚语言是否打算动态链接(新的Go哲学?).
cgo提供了从C(Go内部)调用Go或Go调用C的能力,但不是来自普通C语言.或者是吗?
显然,上游也会发生一些事情(https://codereview.appspot.com/7304104/)
main.c中
extern void Print(void) __asm__ ("example.main.Print");
int main() {
Print();
}
Run Code Online (Sandbox Code Playgroud)
print.go
package main
import "fmt"
func Print() {
fmt.Printf("hello, world\n")
}
Run Code Online (Sandbox Code Playgroud)
Makefile:
all: print.o main.c
gcc main.c -L. -lprint -o main
print.o: print.go
gccgo -fno-split-stack -fgo-prefix=example -fPIC -c print.go -o print.o
gccgo -shared print.o -o libprint.so
Run Code Online (Sandbox Code Playgroud)
输出:
/usr/lib/libgo.so.3: undefined reference to `main.main'
/usr/lib/libgo.so.3: undefined reference to `__go_init_main'
Run Code Online (Sandbox Code Playgroud)
有解决方案吗?什么是最好的方法?分叉+ IPC?
参考文献: