将C++代码用C作一次封装,就可以让Go调用了。
这是一个C++头文件:
#ifndef CGO_CPPGO_CLASS_H_#define CGO_CPPGO_CLASS_H_#includeclass X{public: X(int32_t a); ~X(); void Plus(); int32_t Func(int32_t b);private: int32_t m_;};#endif
这是对应的源文件:
#includeusing std::cout;using std::endl;#include "class.h"X::X(int32_t a) :m_{ a }{ cout << "X::X" << endl;}X::~X(){ cout << "X::~X" << endl;}void X::Plus(){ m_ += 1;}int32_t X::Func(int32_t b){ return m_ + b;}
为了让Go感知不到C++(class、std::cout等)的存在,定义一个结构体:
typedef struct _X_t{ int unused;}X_t;
这个结构体来充当class X的作用。
完整的C头文件如下:(这个头文件中没有任何C++特有的东西!)
#ifndef C_WRAPPER_H_#define C_WRAPPER_H_#includetypedef struct _X_t{ int unused;}X_t;#ifdef __cplusplus#define EXTERN_C extern "C"#else#define EXTERN_C#endifEXTERN_C X_t *NewX(int32_t a); // 充当构造函数EXTERN_C void Delete(X_t *px); // 充当析构函数EXTERN_C void Plus(X_t *px);EXTERN_C int32_t Func(X_t *px, int32_t b);#endif
源文件(.cpp)如下:
#include "c-wrapper.h"#include "class.h"X_t *NewX(int32_t a){ X *px = new X{ a }; return (X_t*)px;}void Delete(X_t *px){ X *p = (X*)px; delete p;}void Plus(X_t *px){ ((X*)px)->Plus();}int32_t Func(X_t *px, int32_t b){ return ((X*)px)->Func(b);}
接下来,就可以在Go中包含c-wrapper.h文件:
package mainimport ( "fmt")/*#cgo CPPFLAGS: -std=c++11#include "c-wrapper.h"*/import "C"func main() { px := C.NewX(3) C.Plus(px) var n int32 = int32(C.Func(px, 7)) fmt.Println(n) C.Delete(px)}
结果如下:
X::X11X::~X
这就实现了Go使用C++代码。
如果想在Go中使用大型C++开源库,这个方法有些麻烦(而且C++的编译比较慢),但不失为一种选择。