9

我有一个要移植到 C++ 的 C 库,它大量使用手动引用计数的结构。我考虑过使用shared_ptr自动处理引用计数,但我也想维护 C API。旧签名看起来像这样:

Object* object_create(void);
Object* object_retain(Object* o);
void object_release(Object* o);

如果我使用shared_ptr,有没有办法在 C API 中有效地公开这个手动引用计数?

4

3 回答 3

7

shared_ptr正如您已经发现的那样,问题在于您无法修改引用计数,除非通过构造或销毁实例。所以不,没有办法让它工作,除非保持 ashared_ptr到每个构造Object周围,直到它的引用计数下降到零,但是这样做需要重做大部分引用计数,所以你得到的很少。

或许boost::intrusive_ptr是更好的选择。

于 2013-06-15T18:00:52.473 回答
1

您可以使用std::shared_ptr::getobject_create.

我不确定您是否应该维护object_retainobject_release因为它已经由shared_ptr.

你想让你的库被 C 代码使用吗?如果是这样,那么正如@Angew 在他的评论中指出的那样,看看 Boost.intrusive_ptr,它似乎是最好的选择。

如果您可以假设用 C 编写的客户端代码将使用 C 库(我认为这是有道理的),那么您可以完全放弃这些函数并在内部处理所有内容。如果需要,您可以提供与 C api 兼容的原始指针,但所有生命周期管理都可以使用shared_ptr.

于 2013-06-15T17:46:29.123 回答
0

由于 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);
}
于 2019-02-21T17:24:13.243 回答