Skip to content

[BUG] Problem when creating derived Python objects from C++ (inheritance slicing) #1333

Description

@mhochsteger

EDIT(eric): Adding a tracking list.


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<iostream>
#include<memory>using std::cout;
using std::endl;
using std::unique_ptr;
using std::shared_ptr;
using std::make_shared;
namespacepy= pybind11;
classBase {
public:virtualvoidPrint() { cout << "Base!" << endl;
}
virtual shared_ptr<Base> Clone() {
return make_shared<Base>();
}
};
classPyBase : publicBase {
public:using Base::Base; // Inherit constructorsvoidPrint() override { PYBIND11_OVERLOAD(void, Base, Print, ); }
shared_ptr<Base> Clone() override { PYBIND11_OVERLOAD(shared_ptr<Base>, Base, Clone, ); }
};
PYBIND11_MODULE(libtest, m) {
py::class_<Base, py::wrapper<PyBase>, shared_ptr<Base>>(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

fromlibtestimport*classDerived(Base):
def__init__(self):
super().__init__()
defPrint(self):
print("Derived!")
defClone(self):
returnDerived()
Test(Derived())

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

holdersIssues and PRs regarding holders

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions