为面向对象的 C++ 代码开发 C 包装器 API
我希望开发一组 C API,这些 API 将环绕我们现有的 C++ API 以访问我们的核心逻辑(用面向对象的 C++ 编写).这本质上是一个胶水 API,允许我们的 C++ 逻辑被其他语言使用.有哪些好的教程、书籍或最佳实践介绍了将 C 封装在面向对象的 C++ 中所涉及的概念?
I'm looking to develop a set of C APIs that will wrap around our existing C++ APIs to access our core logic (written in object-oriented C++). This will essentially be a glue API that allows our C++ logic to be usable by other languages. What are some good tutorials, books, or best-practices that introduce the concepts involved in wrapping C around object-oriented C++?
推荐答案
这并不难手工完成,但取决于界面的大小.我所做的案例是在纯 C 代码中启用我们的 C++ 库,因此 SWIG 没有太大帮助.(好吧,也许 SWIG 可以用来做到这一点,但我不是 SWIG 大师,这似乎很重要)
This is not too hard to do by hand, but will depend on the size of your interface. The cases where I've done it were to enable use of our C++ library from within pure C code, and thus SWIG was not much help. (Well maybe SWIG can be used to do this, but I'm no SWIG guru and it seemed non-trivial)
我们最终做的就是:
- 每个对象都在 C 中传递一个不透明的句柄.
- 构造函数和析构函数被包裹在纯函数中
- 成员函数是纯函数.
- 其他内置函数尽可能映射到 C 等效项.
这样的类(C++ 头文件)
So a class like this (C++ header)
class MyClass
{
public:
explicit MyClass( std::string & s );
~MyClass();
int doSomething( int j );
}
将映射到这样的 C 接口(C 头文件):
Would map to a C interface like this (C header):
struct HMyClass; // An opaque type that we'll use as a handle
typedef struct HMyClass HMyClass;
HMyClass * myStruct_create( const char * s );
void myStruct_destroy( HMyClass * v );
int myStruct_doSomething( HMyClass * v, int i );
接口的实现看起来像这样(C++源代码)
The implementation of the interface would look like this (C++ source)
#include "MyClass.h"
extern "C"
{
HMyClass * myStruct_create( const char * s )
{
return reinterpret_cast<HMyClass*>( new MyClass( s ) );
}
void myStruct_destroy( HMyClass * v )
{
delete reinterpret_cast<MyClass*>(v);
}
int myStruct_doSomething( HMyClass * v, int i )
{
return reinterpret_cast<MyClass*>(v)->doSomething(i);
}
}
我们从原始类派生我们的不透明句柄以避免需要任何强制转换,并且 (这似乎不适用于我当前的编译器).我们必须使句柄成为结构体,因为 C 不支持类.
We derive our opaque handle from the original class to avoid needing any casting, and (This didn't seem to work with my current compiler). We have to make the handle a struct as C doesn't support classes.
这样就为我们提供了基本的 C 接口.如果您想要一个更完整的示例来展示您可以集成异常处理的一种方式,那么您可以在 github 上尝试我的代码:https://gist.github.com/mikeando/5394166
So that gives us the basic C interface. If you want a more complete example showing one way that you can integrate exception handling, then you can try my code on github : https://gist.github.com/mikeando/5394166
现在有趣的部分是确保您将所有必需的 C++ 库正确链接到更大的库中.对于 gcc(或 clang),这意味着只使用 g++ 进行最后的链接阶段.
The fun part is now ensuring that you get all the required C++ libraries linked into you larger library correctly. For gcc (or clang) that means just doing the final link stage using g++.
相关文章