10分钟
2.8.1.2 用纯C函数接口封装 C++ 类
如果要将上面的C++类用C语言函数接口封装,我们可以从使用方式入手。我们可以将new和delete映射为C语言函数,将对象的方法也映射为C语言函数。
在C语言中我们期望MyBuffer类可以这样使用:
int main() {
MyBuffer* pBuf = NewMyBuffer(1024);
char* data = MyBuffer_Data(pBuf);
auto size = MyBuffer_Size(pBuf);
DeleteMyBuffer(pBuf);
}
先从C语言接口用户的角度思考需要什么样的接口,然后创建 my_buffer_capi.h
头文件接口规范:
// my_buffer_capi.h
typedef struct MyBuffer_T MyBuffer_T;
MyBuffer_T* NewMyBuffer(int size);
void DeleteMyBuffer(MyBuffer_T* p);
char* MyBuffer_Data(MyBuffer_T* p);
int MyBuffer_Size(MyBuffer_T* p);
然后就可以基于C++的MyBuffer类定义这些C语言包装函数。我们创建对应的my_buffer_capi.cc
文件如下:
// my_buffer_capi.cc
#include "./my_buffer.h"
extern "C" {
#include "./my_buffer_capi.h"
}
struct MyBuffer_T: MyBuffer {
MyBuffer_T(int size): MyBuffer(size) {}
~MyBuffer_T() {}
};
MyBuffer_T* NewMyBuffer(int size) {
auto p = new MyBuffer_T(size);
return p;
}
void DeleteMyBuffer(MyBuffer_T* p) {
delete p;
}
char* MyBuffer_Data(MyBuffer_T* p) {
return p->Data();
}
int MyBuffer_Size(MyBuffer_T* p) {
return p->Size();
}
因为头文件my_buffer_capi.h
是用于CGO,必须是采用C语言规范的名字修饰规则。在C++源文件包含时需要用extern "C"
语句说明。另外MyBuffer_T的实现只是从MyBuffer继承的类,这样可以简化包装代码的实现。同时和CGO通信时必须通过MyBuffer_T
指针,我们无法将具体的实现暴露给CGO,因为实现中包含了C++特有的语法,CGO无法识别C++特性。
将C++类包装为纯C接口之后,下一步的工作就是将C函数转为Go函数。
学员评价