Pybind11: Transfer Class Ownership To C++ On Construct
I'm having an issue where a python class, which is derived from a c++ base class using pybind11, is being immediately destructed (garbage collected). I would like C++ to take owne
Solution 1:
The correct (I think) way to use std::shared_ptr<A>
as the A
holder is to add it to class_<A...>
arguments.
You also want to replace every instance of A*
with std::shared_ptr<A>
, and new
with std::make_shared
. I think non-default return policies are not needed in this case, so I have removed them; YMMV.
Working module below (with minor errors corrected).
#include<pybind11/pybind11.h>#include<memory>#include<iostream>namespace py = pybind11;
classA
{
public:
A(){};
A(const A&) { std::cout << "Copying A\n"; }
virtual ~A()
{
std::cout << "In A::~A()\n";
};
virtualconstchar* SayHello(){
constchar* x = "\n\nHello from Class A\n\n";
return x;
}
};
classATrampoline : public A
{
public:
using A::A;
constchar* SayHello()override{
PYBIND11_OVERLOAD( constchar*,A,SayHello,);
}
};
classB
{
public:
B()
{
std::cout << "In Class B Constructor\n";
}
B(const B&) { std::cout << "Copying B\n"; }
voidRun(){
aBase = AllocateAnAClass();
std::cout << aBase->SayHello();
}
virtual ~B()
{
}
std::shared_ptr<A> aBase;
virtual std::shared_ptr<A> AllocateAnAClass(){
return std::make_shared<A>();
}
};
classBTrampoline : public B
{
public:
using B::B;
std::shared_ptr<A> AllocateAnAClass()override{
PYBIND11_OVERLOAD(std::shared_ptr<A>,B,AllocateAnAClass,);
}
};
PYBIND11_MODULE(TestModule,m)
{
py::class_<A,std::shared_ptr<A>, ATrampoline>(m,"A")
.def(py::init<>())
.def("SayHello",&A::SayHello);
py::class_<B, BTrampoline>(m,"B")
.def(py::init<>())
.def("Run",&B::Run)
.def("AllocateAnAClass",&B::AllocateAnAClass);
}
Solution 2:
py::nodelete was the solution. While n.m's answer DOES work, it would require going back and chaning all of the pointer in an existing libary to smart pointers, which isn't a viable option for me. Using py::nodelete allows me to do everything on the pybind11 side.
py::class_<A,ATramploline,std::unique_ptr<A,py::nodelete> >(m,"A")
.def(py::init<>())
.def("SayHello",&A::SayHello);
Post a Comment for "Pybind11: Transfer Class Ownership To C++ On Construct"