在新的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
(我使用 avoid*而不是 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