I have a function that takes a std::shared_ptr, and I want to pass an object of Derived type to this function from python. Here's my class definitions:
struct AbstractBase {
virtual void foo() = 0;
};
struct Derived : public AbstractBase {
virtual void foo(){
std::cout<<"Derived's foo!"<<std::endl;
}
};
struct Unrelated {
void bar(std::shared_ptr<AbstractBase> base_shared_ptr) {
base_shared_ptr->foo();
}
};
#endif /* CLASSES_H */
A simple pure C++ example does what I want:
int main()
{
std::shared_ptr<Derived> d(new Derived);
Unrelated u;
u.bar(d);
}
output: Derived's foo!
Here is my Boost.Python Wrapper code:
#include <boost/python.hpp>
#include "classes.h"
BOOST_PYTHON_MODULE(shared_ptr_test) {
using namespace boost::python;
class_<AbstractBase,std::shared_ptr<AbstractBase>,boost::noncopyable>("AbstractBase",no_init);
class_<Derived,std::shared_ptr<Derived>,bases<AbstractBase>,boost::noncopyable>("Derived");
class_<Unrelated,std::shared_ptr<Unrelated>,boost::noncopyable>("Unrelated")
.def("bar",&Unrelated::bar);
}
And here's my simple python test:
import shared_ptr_test
d=shared_ptr_test.Derived()
u=shared_ptr_test.Unrelated()
u.bar(d)
To my dismay, this does not work. It compiles fine, but when I run the python script, I get this error:
Traceback (most recent call last):
File "test.py", line 5, in <module>
u.bar(d)
Boost.Python.ArgumentError: Python argument types in
Unrelated.bar(Unrelated, Derived)
did not match C++ signature:
bar(Unrelated {lvalue}, std::shared_ptr<AbstractBase>)
Changing bar
to take a shared_ptr<Derived>
fixes this, so I know that internally Boost.Python is managing the objects with shared_ptr
s. Is there something more I need to do to get Boost.Python to realize that it is okay to pass a shared_ptr<Derived>
to a function expecting a shared_ptr<Base>
?
Boost.Python needs to be aware that a smart pointer to
Derived
can be converted to a smart pointer toAbstractBase
. This can be accomplished by either of the following:boost::shared_ptr
. Boost.Python has code to handle implicit conversions betweenboost::shared_ptr
s when theirelement_type
are hierarchical.Register an implicit conversion from
std::shared_ptr<Derived>
tostd::shared_ptr<AbstractBase>
viaboost::python::implicitly_convertible
.std::shared_ptr
meets the concept requirements for theimplicitly_convertible
, so it only requires registering the conversion in the module definition: