-
I am working on a bindings project and encountered some bizarre behavior when deriving a C++ class in Python, and then sending that Python class back to C++. I'm not sure if this is a bug with pybind11, a limitation with Python, or me doing something wrong. Here is a minimal example that reproduces my problem: namespace pyb = pybind11;
// Inheritable base class A
class A {
public:
virtual void say() {
std::cout << "say() called from A" << std::endl;
}
};
class PyA : public A {
public:
void say() override { PYBIND11_OVERRIDE(void, A, say); }
};
pyb::class_<A, PyA, std::shared_ptr<A>>(m, "A")
.def(pyb::init<>());
// Container that holds an A reference
struct AHolder {
std::shared_ptr<A> aRef = NULL;
};
pyb::class_<AHolder>(m, "AHolder")
.def(pyb::init<>())
.def_readwrite("a_ref", &AHolder::aRef);
// C++ function that use an AHolder
m.def("use_holder",
[](const AHolder& holder) {
holder.aRef->say();
}
); Then, in python: class B(A):
def say(self):
print("say() called from B")
holder = AHolder()
holder.a_ref = B()
use_holder(holder) This outputs However, if I edit the Python code to assign holder = AHolder()
-holder.a_ref = B()
+b = B()
+holder.a_ref = b
use_holder(holder) Then, it correctly outputs Is this a bug? If not, can I do something about it? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
I managed to find someone's solution that completely fixes this problem: #2839 |
Beta Was this translation helpful? Give feedback.
I managed to find someone's solution that completely fixes this problem: #2839
The issue is that pybind normally does not keep the derived python object alive, which is what that PR fixes.