Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ smart pointer to external managed (e.g: Python) resources?

Is there a smart pointer in C++ to a resource managed by others? I am using pybind11 to wrap C++ code as followed.

    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 *>());
    }

Then in python, I'll use them as followed:

    b = B()
    a = A(b)

This is fine as long as I don't del a. When I del a in python, the shared_ptr mb I created in C++'s 'A' will try to destroy B object, which is managed by Python and crash. So, my question is if there is some smart pointer in C++ that don't take ownership from a raw pointer? weak_ptr won't work because I'll still have to create a shared_ptr.

like image 428
hlu58 Avatar asked Feb 18 '26 12:02

hlu58


1 Answers

Pybind11 is using a unique pointer behind the scenes to manage the C++ object as it thinks it owns the object, and should deallocate the object whenever the Python wrapper object is deallocated. However, you are sharing this pointer with other parts of the C++ code base. As such, you need to make the Python wrapper of the B class to manage the instance of B using a shared pointer. You can do this in the with class_ template. eg.

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

like image 103
Dunes Avatar answered Feb 20 '26 01:02

Dunes