我有一个C库,我正在移植到C ++,它大量使用手动引用计数的结构。我已经考虑使用shared_ptr
来自动处理引用计数,但我还想维护C API。旧签名看起来像这样:
Object* object_create(void);
Object* object_retain(Object* o);
void object_release(Object* o);
如果我使用shared_ptr
,有没有办法在C API中有效地公开此手动引用计数?
答案 0 :(得分:7)
shared_ptr
的问题,正如您已经想到的那样,除了通过构造或销毁实例之外,您无法修改引用计数。所以不,没有办法让它工作,除非保持shared_ptr
到每个构造的Object
,直到它的引用计数降到零,但这样做需要重做大部分引用计数,所以你收获很少。
或许boost::intrusive_ptr
是更好的选择。
答案 1 :(得分:1)
您可以使用std::shared_ptr::get
在object_create
中检索指针的值。
我不确定您应该维护object_retain
还是object_release
,因为它已由shared_ptr
自动处理。
您希望C代码使用您的库吗?如果是这样,那么@Angew在他的评论中指出,看看Boost.intrusive_ptr,它似乎是最好的选择。
如果你可以假设用C语言编写的客户端代码将使用C库(我认为有意义),那么你可以完全删除这些函数并在内部处理所有函数。如果需要,您可以提供与C api兼容的原始指针,但可以使用shared_ptr
自动处理所有生命周期管理。
答案 2 :(得分:0)
由于C中没有RAII,因此您将需要通过create / destroy函数自己管理共享指针。因此,您返回的句柄应为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);
}