我有一个常见的问题就是为C库编写一个C ++包装器...我的主存储器是一个C-Struct指针,它们总是代表一个只包含 ONE 数据字段的C ++类。
class MyClassC {
struct MyStructS * hdl
...
}
创建所有构造函数,静态和方法函数是没有问题...我的设计问题现在是......我应该使用值类设计还是指针类设计。
值类在 MyStructS 和 MyClassC ONE 到 MANY 的关系>
MyClassC myMethod () {
...
return MyClassC(struct MyStructS *...);
}
值类的析构函数从不免费 struct MyStructS指针,并且大部分为空
值的析构函数是静态或方法,主要称为 destry 或 delete
MyClassC::delete() {
DestroyMyPointer(&hdl)
}
...
MyClassC obj = {...};
...
obj.delete();
...
value 类也是方法 value 的参数:
some_proc_or_method (MyClassC arg1, MyClassC arg2, …) {
...
}
还有一个问题:
如何为值类参数创建默认参数?
some_proc_or_method (MyClassC arg1, MyClassC arg2 = MyClassC {...} ???? ) {
...
}
MyClassC* myMethod () {
...
return this or getThisFrom(myStructS_pointer)
}
指针类的析构函数总是免费 struct MyStructS指针
~MqClassC () {
DestroyMyPointer(&hdl)
}
...
MyClassC* obj = new MyClassC(...);
...
delete obj;
...
答案 0 :(得分:0)
我选择选项3:一个薄的包装器,首先获得所有权。 C代码在C ++中已经很有用了。获得包装它的唯一实际好处是获得所有权语义正确。您的两种方法都试图将所有权跟踪到您的API用户身上。这不是一个有用的包装器,它只是添加了一个多余的间接层。您的客户仍需要注意C API的内部有效。
我建议的是你返回一个具有明确所有权语义的智能指针。编写一堆内联自由函数,接受智能指针并转发到C API。最终结果是,您具有几乎相同的API(较少的学习曲线),具有C ++所有权语义。这是一个收获,结果将不那么繁琐。
#include <memory>
#include <CLibAPI.h>
namespace CPPWrapC {
namespace detail {
struct DestroyMyPointer {
void operator()(MyStructS *hdl) {
::DestroyMyPointer(&hdl);
}
};
}
using Handle = std::unique_ptr<MyStructS, detail::DestroyMyPointer>;
Handle myMethod() {
MyStructS *ret = /* init it */;
return Handle{ret};
}
inline void some_proc_or_method(Handle const& hdl) {
c_lib_some_proc_or_method(hdl.get());
}
}
所以现在你有一个简单的包装器,支持具有单一所有权语义的句柄。我想你到底想要什么。使用它几乎就像使用原始包装的API一样,因此客户可以充分利用他们对C库的了解。
这可以作为踏脚石。现在你有了一个C ++类型,你可以将其作为成员包含在内,以便进一步包装。