【问题标题】:Using shared_ptr in C interfaces?在 C 接口中使用 shared_ptr?
【发布时间】:2013-06-15 17:36:47
【问题描述】:

我有一个要移植到 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 包装从object_create 获得的原始指针,并让它在相关时间调用object_release
  • 你最好使用Boost.intrusive_ptr
  • 嗯,好的。好吧,您可以从 shared_ptr 获取原始指针没问题,(请参阅stackoverflow.com/questions/505143/…),但正如您所料,没有跟踪原始指针的去向(此时它完全在引用计数机制之外)。
  • 在 c 中实现为结构,在 c++ 中实现类?这样就少了很大的痛苦。
  • std::enable_shared_from_this 可能对您有用,但不幸的是,您需要至少有一个来自 C++ 代码的 shared_ptr 引用:请参阅stackoverflow.com/questions/4428023/…

标签: c++ c shared-ptr


【解决方案1】:

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

也许boost::intrusive_ptr 是一个更好的选择。

【讨论】:

    【解决方案2】:

    您可以使用std::shared_ptr::get 检索object_create 中指针的值。

    我不确定您是否应该维护object_retainobject_release,因为它已经由shared_ptr 自动处理。

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

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

    【讨论】:

    • C 端不会自动维护引用计数。如果最后一个 shared_ptrObject 被销毁,但仍有一个 Object* 指向它,则该对象被销毁并且 C 指针悬空。
    • 没错,我在想一个用作对象查看器的原始指针,假设 shared_ptr 将处理对象的生命周期。
    【解决方案3】:

    由于 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);
    }
    

    【讨论】:

      猜你喜欢
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      • 2017-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-24
      相关资源
      最近更新 更多