0

我有一个常见的问题是为 C 库编写 C++ 包装器……我的主要存储是一个 C-Struct 指针,它始终表示一个 C++ 类,其中只包含一个数据文件。

class MyClassC {
  struct MyStructS * hdl
  ...
}

创建所有的构造函数、静态函数和方法函数没问题……我的设计问题是现在……我应该使用类设计还是指针类设计。

类总是返回对象而不是指针:

类在MyStructSMyClassC之间具有ONE to MANY关系

MyClassC myMethod () {
  ...
  return MyClassC(struct MyStructS *...);
}

类的析构函数从不释放struct MyStructS 指针并且大部分为空

的析构函数是静态方法,主要称为destrydelete

MyClassC::delete() {
   DestroyMyPointer(&hdl)
}
...
MyClassC obj = {...};
...
obj.delete();
...

类也是方法的参数

some_proc_or_method (MyClassC arg1, MyClassC arg2, …) {
   ...
} 

还有一个问题:

如何为类参数创建默认参数?

some_proc_or_method (MyClassC arg1, MyClassC arg2 = MyClassC {...} ???? ) {
   ...
} 

指针类总是返回对象的指针:

指针类在MyStructSMyClassC之间具有一对一关系

MyClassC* myMethod () {
  ...
  return this or getThisFrom(myStructS_pointer)
}

指针类的析构函数总是释放struct MyStructS 指针

~MqClassC () {
   DestroyMyPointer(&hdl)
 }

...
MyClassC* obj = new MyClassC(...);
...
delete obj;
...
4

1 回答 1

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++ 类型,您可以将其作为成员包括在内以进一步包装事物。

于 2018-06-17T10:01:47.310 回答