在新的Go语言中,如何调用C 代码?换句话说,如何包装我的C 类并在Go中使用它们?
更新: 我已经成功地将一个小型测试C ++类与Go链接在一起
如果您使用C接口包装C ++代码,则应该可以使用cgo调用您的库(请参阅中的gmp示例$GOROOT/misc/cgo/gmp)。
$GOROOT/misc/cgo/gmp
我不确定C ++中的类概念是否真的可以在Go中表达,因为它没有继承。
这是一个例子:
我有一个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
(我使用a void*而不是C结构,因此编译器知道Foo的大小)
void*
实现是:
//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)
尝试使用以下方法进行测试:
// 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