我有一个要移植到 C++ 的 C 库,它大量使用手动引用计数的结构。我考虑过使用shared_ptr
自动处理引用计数,但我也想维护 C API。旧签名看起来像这样:
Object* object_create(void);
Object* object_retain(Object* o);
void object_release(Object* o);
如果我使用shared_ptr
,有没有办法在 C API 中有效地公开这个手动引用计数?
我有一个要移植到 C++ 的 C 库,它大量使用手动引用计数的结构。我考虑过使用shared_ptr
自动处理引用计数,但我也想维护 C API。旧签名看起来像这样:
Object* object_create(void);
Object* object_retain(Object* o);
void object_release(Object* o);
如果我使用shared_ptr
,有没有办法在 C API 中有效地公开这个手动引用计数?
shared_ptr
正如您已经发现的那样,问题在于您无法修改引用计数,除非通过构造或销毁实例。所以不,没有办法让它工作,除非保持 ashared_ptr
到每个构造Object
周围,直到它的引用计数下降到零,但是这样做需要重做大部分引用计数,所以你得到的很少。
或许boost::intrusive_ptr
是更好的选择。
您可以使用std::shared_ptr::get
在object_create
.
我不确定您是否应该维护object_retain
或object_release
因为它已经由shared_ptr
.
你想让你的库被 C 代码使用吗?如果是这样,那么正如@Angew 在他的评论中指出的那样,看看 Boost.intrusive_ptr,它似乎是最好的选择。
如果您可以假设用 C 编写的客户端代码将使用 C 库(我认为这是有道理的),那么您可以完全放弃这些函数并在内部处理所有内容。如果需要,您可以提供与 C api 兼容的原始指针,但所有生命周期管理都可以使用shared_ptr
.
由于 C 中没有 RAII,因此您需要通过创建/销毁函数自己管理共享指针。所以你返回的句柄应该是 shared_ptr-s,你的 API 应该是这样的:
// Opaque pointer wrapped in structure for type safety (in header)
typedef struct
{
void *ptr;
} ObjectHandle;
// Hide the gory details of resolving the shared ptr.
static std::shared_ptr<Object>* resolveHandle(ObjectHandle objectHandle)
{
return static_cast<std::shared_ptr<Object>*>(objectHandle.ptr);
}
// Just a sample on how to fully resolve the object for internal use.
static Object* resolveObject(ObjectHandle objectHandle)
{
return resolveHandle(objectHandle)->get();
}
// Public API functions.
ObjectHandle object_create(void)
{
return ObjectHandle{new std::shared_ptr<Object>(new Object())};
}
ObjectHandle object_retain(ObjectHandle o)
{
return ObjectHandle{new std::shared_ptr<Object>(*resolveHandle(o))};
}
void object_release(ObjectHandle o)
{
delete resolveHandle(o);
}