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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With