指向外部托管(例如:Python)资源的 C++ 智能指针?

Posted

技术标签:

【中文标题】指向外部托管(例如:Python)资源的 C++ 智能指针?【英文标题】:C++ smart pointer to external managed (e.g: Python) resources? 【发布时间】:2018-12-14 21:14:21 【问题描述】:

C++ 中是否有指向他人管理资源的智能指针?我正在使用 pybind11 来包装 C++ 代码,如下所示。

    class B ;
    class A 
      public:
        // original C++ class interface
        A(std::shared_ptr<B> pb) : mb(pb)
        // have to add this for pybind11, since pybind11 doesn't take shared_ptr as argument.
        A(B * pb):A(std::shared_ptr<B>(pb))
      private:
        std::shared_ptr<B> mb;
    
    namespace py = pybind11;
    PYBIND11_MODULE(test, m)
    
       py::class_<B>(m, "B")
       .def(py::init<>());

       py::class_<A>(m, "A")
       .def(py::init<B *>());
    

然后在python中,我将按如下方式使用它们:

    b = B()
    a = A(b)

只要我不删除就可以了。当我在 python 中 del a 时,我在 C++ 的“A”中创建的 shared_ptr mb 将尝试破坏由 Python 管理的 B 对象并崩溃。所以,我的问题是 C++ 中是否有一些智能指针不从原始指针获取所有权? weak_ptr 不起作用,因为我仍然需要创建一个 shared_ptr。

【问题讨论】:

如果智能指针没有以某种方式取得所有权,您希望它的行为是什么? 你可以使用一个什么都不做的自定义删除器。 【参考方案1】:

Pybind11 在后台使用唯一指针来管理 C++ 对象,因为它认为它拥有该对象,并且应该在 Python 包装器对象被释放时释放该对象。但是,您正在与 C++ 代码库的其他部分共享此指针。因此,您需要制作 B 类的 Python 包装器,以使用共享指针管理 B 的实例。您可以在 class_ 模板中执行此操作。例如。

PYBIND11_MODULE(test, m)

   py::class_<B, std::shared_ptr<B> >(m, "B")
   .def(py::init<>());

   py::class_<A>(m, "A")
   .def(py::init<std::shared_ptr<B> >());

https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html#std-shared-ptr

【讨论】:

谢谢,您的解决方案运行良好。我试图删除“b”,对象“a”仍然可以毫无问题地访问其内部保存的“mb”。

以上是关于指向外部托管(例如:Python)资源的 C++ 智能指针?的主要内容,如果未能解决你的问题,请参考以下文章

C#嵌入dll到资源释放的问题

C# 中的非托管 C++ 类

如何从 C# 导入和使用非托管 C++ 类?

IDisposeable 最佳实现

指向外部站点的 Cordova webview 未加载图像

Visual Studio 非托管 C++ 智能文件资源管理器