【问题标题】:Go shared library as C++ pluginGo 共享库作为 C++ 插件
【发布时间】:2013-05-24 06:01:54
【问题描述】:

我有一个项目,我想在 C++ 应用程序中加载 Go 插件。

经过大量研究,我不清楚 Go 是否支持这一点。 我遇到很多讨论指出动态链接的坏习惯,而不是使用 IPC。此外,我不清楚动态链接是否是该语言的意图(新的 Go 哲学?)。

cgo 提供了从 Go 调用 C 或从 C(在 Go 内部)调用 Go 的能力,但不能从普通的旧 C 调用。或者是吗?

显然上游也发生了一些事情 (https://codereview.appspot.com/7304104/)

ma​​in.c

extern void Print(void) __asm__ ("example.main.Print");

int main() {
        Print();
}

print.go

package main

import "fmt"

func Print() {
    fmt.Printf("hello, world\n")
}

生成文件:

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

输出:

/usr/lib/libgo.so.3: undefined reference to `main.main'
/usr/lib/libgo.so.3: undefined reference to `__go_init_main'

有解决办法吗?最好的方法是什么?分叉+IPC?

参考文献:

【问题讨论】:

  • 推荐的解决方案是让你的主程序启动你的 Go-plugin 作为一个外部进程,通过管道连接到你的主程序。更少的麻烦和更少的安全风险

标签: c++ go shared-libraries


【解决方案1】:

我不认为你可以将 Go 嵌入到 C 中。但是你可以将 C 嵌入到 Go 中,并且通过一个小的存根 C 程序你可以首先调用 C,这是下一个最好的事情! Cgo 绝对支持与共享库的链接,所以也许这种方法对你有用。

这样

ma​​in.go

// Stub go program to call cmain() in C
package main

// extern int cmain(void);
import "C"

func main() {
     C.cmain()
}

ma​​in.c

#include <stdio.h>

// Defined in Go
extern void Print(void);

// C Main program
int cmain() {
  printf("Hello from C\n");
  Print();
}

print.go

package main

import "fmt"

import "C"

//export Print
func Print() {
    fmt.Printf("Hello from Go\n")
}

使用go build 编译,并在运行时生成此输出

Hello from C
Hello from Go

【讨论】:

  • 感谢您的回答!但是,我假设 C++ 运行时首先在没有加载任何插件的情况下启动。然后,我根据需要加载 Go 插件(组件配置器模式)。根据您的示例,我不确定从 Go 调用 C 是否会对我有所帮助。
  • 上述答案旨在向您展示一种使问题中的代码正常工作的方法。唉,它不是使用 Go 插件扩展 C++ 的解决方案。 Go 还没有创建共享对象——它是静态链接的,所以如果你希望能够在运行时插入 Go 代码,你将不得不使用子进程和 IPC。如果您对预编译的一组静态插件感到满意,那么您可能会使用上述技术与 C++ 一起使用,但您需要一些未知的额外魔法来启动 C++ 运行时。
【解决方案2】:

AFAIK,你不能将 Go 包编译到共享库 wtg 'gc' ATM,它可能会在未来改变。 'gccgo' 可能有一些机会,因为'libgo'(我想是 Go 运行时)已经是一个共享库。我猜缺少的部分只是正确初始化运行时,通常 Go 命令会自动处理。

gccgo 专家是 I.L. Taylor,几乎每天都可以通过 golang-nuts 邮件列表联系到他。我建议直接问他。

PS:其他问题可能包括Go垃圾收集器和(C++)进程内存的交互等。可能我太乐观了,根本不可行。

【讨论】:

    猜你喜欢
    • 2010-12-17
    • 2014-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    相关资源
    最近更新 更多