I am having a strange problem when calling a C++ function in python.
I exposed a class from which I want to call a function:
class_<MyClass, std::shared_ptr<MyClass>>("MyClass", init<>())
// ...
.def("someFunc", &MyClass::someFunc)
;
I get a std::shared_ptr<MyClass>
from a member variable from another class which is exposed via .def_readonly(...)
When I try to call the function, I get the following error:
File "pytest.py", line 27, in test_func
cu.someFunc("string")
Boost.Python.ArgumentError: Python argument types in
MyClass.someFunc(MyClass, str)
did not match C++ signature:
result(MyClass{lvalue}, std::string)
As far as I see, the signatures do match. Does someone see the problem?
Haven't tested it, but this may work:
Source: http://www.boost.org/doc/libs/1_55_0/libs/python/doc/v2/register_ptr_to_python.html
As tracked in this ticket, Boost.Python does not fully support
std::shared_ptr
.In short, two easy solutions are to either:
boost::shared_ptr
instead ofstd::shared_ptr
.std::shared_ptr
member variable with viaadd_property()
, providing aboost::python::return_value_policy
with a type ofboost::python::return_by_value
.While the signatures in the exception look the same, the subtle detail is that the Python
MyClass
object embeds astd::shared_ptr<MyClass>
. Thus, Boost.Python must perform a conversion from anstd::shared_ptr<MyClass>
to an lvalueMyClass
. However, Boost.Python does not currently support custom lvalue conversions. Thus, anArgumentError
exception is thrown.When exposing member variables with
def_readonly("spam", &Factory::spam)
, it is the equivalent of exposing it via:Boost.Python has special code when the type being exposed in this manner is a
boost::shared_ptr
. As it is a read-only property andstd::shared_ptr
is intended to be copied, it is safe to expose a copy ofstd::shared_ptr
with a return value policy with a type ofreturn_by_value
.Here is a complete example where
Factory
exposes aSpam
object held bystd::shared_ptr
and anEgg
object held byboost::shared_ptr
:Interactive Python demonstrating usage and object lifetime: