Reputation: 622
I have a c++ class that has a unique pointer to an object as an attribute. I would like to be able to access that attribute in Python so I can call its class methods. Here is an example of my setup:
class OuterClass {
public:
std::unique_ptr<InnerClass> obj;
}
class InnerClass {
public:
void method();
}
And the pybind11 bindings:
PYBIND11_MODULE(example, m) {
py::class_<InnerClass>(m, "InnerClass")
.def("method", &InnerClass::method);
py::class_<OuterClass>(m, "OuterClass")
.def_readonly("obj", &OuterClass::obj);
}
However, this fails to compile with the error error: no matching function for call to ‘pybind11::cpp_function::cpp_function(std::unique_ptr<InnerClass> OuterClass::*, pybind11::name, pybind11::is_method, pybind11::sibling)
I would like to be able to do this in python:
outer_obj.obj.method()
The docs for unique ptr does not seem to think this should be a problem as they give an example of a function that returns a unique ptr. Is trying to access a unique ptr attribute the issue? How can I get around this?
Upvotes: 3
Views: 1189
Reputation: 648
Use def_property
with lambda to return the pointer:
class InnerClass {
public:
void method()
{
std::cout << "OK" << std::endl;
}
};
class OuterClass {
public:
OuterClass()
: obj(std::make_unique<InnerClass>())
{
}
std::unique_ptr<InnerClass> obj;
};
PYBIND11_MODULE(example, m) {
py::class_<InnerClass>(m, "InnerClass")
.def("method", &InnerClass::method);
py::class_<OuterClass>(m, "OuterClass", py::dynamic_attr())
.def(py::init<>())
.def_property_readonly("obj", [](const OuterClass& o){return o.obj.get();}, py::return_value_policy::reference_internal);
}
Upvotes: 7