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

推荐答案

Update:我已经成功地将一个小的测试C++类与GO链接起来

如果用C接口包装C++代码,则应该能够用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;
}

我想在围棋中用它.我将使用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 struct ,因此编译器知道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)

试着用以下方法进行测试:

// 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

Go相关问答推荐

Term~T中的类型不能是类型参数,但可以是引用类型参数的切片

链自定义GRPC客户端拦截器/DialOptions

使用GO从RDPMC获得价值

租户GUID X的租户不存在self 邮箱帐户的租户(我是唯一的成员)

可以';t从主机连接到ScyllaDB容器

为什么要立即调用内联函数,而不仅仅是调用其包含的函数?

`docker system df` 与 `/system/df` (docker api 端点)

如何模拟 stripe 需要 webhooks 的捕获事件?

运行 Docker 容器 - X11 无法打开显示:0

在多个 struct 体中重用 Go 中的函数

在golang中以JSON格式获取xwwwformurlencoded请求的嵌套键值对

Golang和Gin web框架在router.Run()之后执行代码

上传图片失败,出现错误dial tcp: lookup api.cloudinary.com: no such host

如何模仿联合类型

查找、解析和验证邮箱地址

GRPC 元数据未在 Go 中更新

将 []float64 像素切片转换为图像

如何正确判断 io.Reader 是否为零?

Golang 泛型同时具有接口和实现

AWS EKS 上的 Golang REST API 部署因 CrashLoopBackOff 而失败