[BUG] Problem when creating derived Python objects from C++ (inheritance slicing) · Issue #1333 · pybind/pybind11 (original) (raw)
EDIT(eric): Adding a tracking list.
- Enumerate possible solutions and drawbacks, e.g.
- Should investigate usage of py::wraper<> trampoline shim with GC garbage collection (to prevent inheritance slicing) #2757 Using
py::wrapper<>
and GC ressurrection - Others...
- Should investigate usage of py::wraper<> trampoline shim with GC garbage collection (to prevent inheritance slicing) #2757 Using
- Identify best path forward, implement.
Issue description
Hello,
Consider deriving a C++ class in Python and overloading virtual functions, including a 'Clone' function.
When passing a derived Python object to C++ without holding a reference (like calling Clone()), the information about the Python type is lost. In this case the wrong base-class function is called. More complex cases may result in a SEGFAULT.
Is there any way to work around/fix this without causing memory leaks?
Thanks!
Reproducible example code
test.cpp
// test.cpp #include <pybind11/pybind11.h> #include <Python.h>
#include #include
using std::cout; using std::endl; using std::unique_ptr; using std::shared_ptr; using std::make_shared;
namespace py = pybind11;
class Base { public: virtual void Print() { cout << "Base!" << endl; }
virtual shared_ptr<Base> Clone() {
return make_shared<Base>();
}
};
class PyBase : public Base { public: using Base::Base; // Inherit constructors void Print() override { PYBIND11_OVERLOAD(void, Base, Print, ); } shared_ptr Clone() override { PYBIND11_OVERLOAD(shared_ptr, Base, Clone, ); } };
PYBIND11_MODULE(libtest, m) { py::class_<Base, py::wrapper, shared_ptr>(m, "Base") .def(py::init<>()) ;
m.def("Test", [] ( shared_ptr<Base> b ) {
shared_ptr<Base> d = b->Clone();
// Python object of d is already dead!
d->Print(); // prints "Base!"
});
}
test.py
from libtest import *
class Derived(Base): def init(self): super().init()
def Print(self):
print("Derived!")
def Clone(self):
return Derived()
Test(Derived())