Pybind11: [regression] calling function with object of derived class: Unable to load a custom holder type from a default-holder instance

Created on 21 Jul 2017  路  3Comments  路  Source: pybind/pybind11

In pybind11 2.0.1, calling a function of a derived class works as expected, e.g.,

struct Base {};
struct Deriv: Base {};
void show(std::shared_ptr<Base> & b) {return;}

PYBIND11_PLUGIN(foo) {
    py::module m("foo");

    py::class_<Base>(m, "Base")
          .def(py::init<>());
    py::class_<Deriv, Base>(m, "Deriv")
          .def(py::init<>());
    m.def("show", &show);
}
import foo
d = foo.Deriv()
foo.show(d)



md5-23c5922ec9e6b4e77fe9228b623c5da5



RuntimeError: Unable to load a custom holder type from a default-holder instance

Most helpful comment

The error is happening because the default holder for pybind classes is std::unique_ptr, which can't be converted to a shared_ptr. 2.1 added detection and failure for this; I'm not entirely sure what would have happened in 2.0 (perhaps a double free?).

The easiest fix is to change the holder on the registered types to shared_ptr with:

py::class_<Base, std::shared_ptr<Base>>(...);
py::class_<Derived, Base, std::shared_ptr<Derived>>(...);

(On a separate note, you'll want to make sure Base has a virtual destructor for anything more than a trivial class.)

All 3 comments

The error is happening because the default holder for pybind classes is std::unique_ptr, which can't be converted to a shared_ptr. 2.1 added detection and failure for this; I'm not entirely sure what would have happened in 2.0 (perhaps a double free?).

The easiest fix is to change the holder on the registered types to shared_ptr with:

py::class_<Base, std::shared_ptr<Base>>(...);
py::class_<Derived, Base, std::shared_ptr<Derived>>(...);

(On a separate note, you'll want to make sure Base has a virtual destructor for anything more than a trivial class.)

Thanks, this fixes it.

It worked! hurrey..

Was this page helpful?
0 / 5 - 0 ratings