如何在Go中使用C ++?

在新的Go语言中,如何调用C ++代码? 换句话说,如何包装我的C ++类并在Go中使用它们?

更新:我成功地将一个小的testingC ++类与Go联系起来

如果你用C接口包装你的C ++代码,你应该可以用cgo调用你的库(请参阅$ GOROOT / misc / cgo / gmp中的gmp示例)。

我不确定C ++中的类是否可以用Go来expression,因为它没有inheritance。

这是一个例子:

我有一个C ++类定义为:

// foo.hpp class cxxFoo { public: int a; cxxFoo(int _a):a(_a){}; ~cxxFoo(){}; void Bar(); }; // foo.cpp #include <iostream> #include "foo.hpp" void cxxFoo::Bar(void){ std::cout<<this->a<<std::endl; } 

我想在Go中使用它。 我将使用C接口

 // foo.h #ifdef __cplusplus extern "C" { #endif typedef void* Foo; Foo FooInit(void); void FooFree(Foo); void FooBar(Foo); #ifdef __cplusplus } #endif 

(我使用void*而不是C结构,所以编译器知道Foo的大小)

实施是:

 //cfoo.cpp #include "foo.hpp" #include "foo.h" Foo FooInit() { cxxFoo * ret = new cxxFoo(1); return (void*)ret; } void FooFree(Foo f) { cxxFoo * foo = (cxxFoo*)f; delete foo; } void FooBar(Foo f) { cxxFoo * foo = (cxxFoo*)f; foo->Bar(); } 

完成所有的工作,Go文件是:

 // foo.go package foo // #include "foo.h" import "C" import "unsafe" type GoFoo struct { foo C.Foo; } func New()(GoFoo){ var ret GoFoo; ret.foo = C.FooInit(); return ret; } func (f GoFoo)Free(){ C.FooFree(unsafe.Pointer(f.foo)); } func (f GoFoo)Bar(){ C.FooBar(unsafe.Pointer(f.foo)); } 

我用来编译的makefile是:

 // makefile TARG=foo CGOFILES=foo.go include $(GOROOT)/src/Make.$(GOARCH) include $(GOROOT)/src/Make.pkg foo.o:foo.cpp g++ $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $< cfoo.o:cfoo.cpp g++ $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $< CGO_LDFLAGS+=-lstdc++ $(elem)_foo.so: foo.cgo4.o foo.o cfoo.o gcc $(_CGO_CFLAGS_$(GOARCH)) $(_CGO_LDFLAGS_$(GOOS)) -o $@ $^ $(CGO_LDFLAGS) 

尝试用以下方法testing

 // foo_test.go package foo import "testing" func TestFoo(t *testing.T){ foo := New(); foo.Bar(); foo.Free(); } 

您需要安装make install来安装共享库,然后运行make test。 预期的产出是:

 gotest rm -f _test/foo.a _gotest_.6 6g -o _gotest_.6 foo.cgo1.go foo.cgo2.go foo_test.go rm -f _test/foo.a gopack grc _test/foo.a _gotest_.6 foo.cgo3.6 1 PASS 

你还不能从我在FAQ中读到的内容中find答案 :

Do Go程序是否与C / C ++程序链接?

有两个Go编译器实现,gc(6g程序和朋友)和gccgo。 Gc使用不同的调用约定和链接器,因此只能使用相同的约定与C程序链接。 有这样一个C编译器,但没有C ++编译器。 Gccgo是一个GCC前端,可以小心地与GCC编译的C或C ++程序链接。

cgo程序提供了一个“外部函数接口”机制,允许从Go代码安全地调用C库。 SWIG将此function扩展到C ++库。

似乎目前SWIG是最好的解决scheme:

http://www.swig.org/Doc2.0/Go.html

它支持inheritance,甚至允许使用Go结构来inheritanceC ++类,所以当在C ++代码中调用重写的方法时,Go代码被激发。

有关Go的FAQ中的C ++部分已经更新,现在提到SWIG,不再说“ 因为Go是垃圾收集,所以这样做是不明智的,至less天真 ”。

截至go1.2 +,cgo自动合并和编译C ++代码:

http://golang.org/doc/go1.2#cgo_and_cpp

看起来这是关于Golang的早期问题之一。 而同一时间的答案永远不会更新。 在这三四年的时间里,新的图书馆和博客太多了。 以下是我觉得有用的几个链接。

SWIG和Go

用SWIG调用C ++代码

比较语言,C ++和Go

GoForCPPProgrammers

在使用gcc Go编译器gccgo时,会谈到C和Go之间的互操作性 。 (例如,有限的goroutines,没有垃圾收集),使用gccgo时Go的互操作性和实现的function集都存在限制。

你走在这个未知的领域。 下面是调用C代码的Go示例,也许你可以在阅读完C ++名称调用和调用约定以及大量的试验和错误之后做类似的事情。

如果你仍然想尝试,祝你好运。

这里的问题是一个兼容的实现不需要把你的类放在一个编译的.cpp文件中。 如果编译器可以优化一个类的存在,只要没有它的程序行为相同,那么它可以从输出可执行文件中省略。

C有一个标准化的二进制接口。 因此,您将能够知道您的function已导出。 但是C ++没有这样的标准。

有趣的是,这个公告已经挖掘了多less更广泛的问题。 Dan Lyke在他的网站Flutterby上进行了一个非常有趣和深思熟虑的讨论,关于将进程间标准 ( Interprocess Standards)作为引导新语言(以及其他分支,但是这里是密切相关的)的一种方式。

您可能需要将-lc++添加到Golang / CGo的LDFlags中,以识别标准库的需求。