No automatic upcasting with std::shared_ptr in function calls?
Hello, I have a sample hierarchy of polymorphic classes (A from which B inherits). One of them (A1, B1) is managed with boost::shared_ptr, the other one (A2, B2) via std::shared_ptr (I defined the get_pointer template for std::shared_ptr). When I call f1(boost::shared_ptr<A1>) with an object B1 from python, it is correctly upcast to the pointer to its base class and the c++ function is called. When I call f2(std::shared_ptr<A2>) with B2 argument from python, no upcasting takes place and I get Boost.Python.Argument error. The code is here: foo.cpp: #include<boost/shared_ptr.hpp> /// make boost::python understand std::shared_ptr #include<memory> namespace boost { template<class T> T* get_pointer(std::shared_ptr<T> p){ return p.get(); } } // define a hierarchy struct A1{ virtual ~A1(){} }; struct B1: public A1{ virtual ~B1(){} }; void f1(boost::shared_ptr<A1> ptr){ std::cerr<<"f1()"<<std::endl; } struct A2{ virtual ~A2(){} }; struct B2: public A2{ virtual ~B2(){} }; void f2(std::shared_ptr<A2> ptr){ std::cerr<<"f2()"<<std::endl; } #include<boost/python.hpp> using namespace boost::python; BOOST_PYTHON_MODULE(foo){ class_<A1,boost::shared_ptr<A1>>("A1"); class_<B1,boost::shared_ptr<B1>,bases<A1>>("B1"); def("f1",f1); class_<A2,std::shared_ptr<A2>>("A2"); class_<B2,std::shared_ptr<B2>,bases<A2>>("B2"); def("f2",f2); } compiling with (under Linux): g++ -std=c++0x foo.cpp -o foo.so -fPIC -shared -lboost_python `pkg-config python --libs --cflags` Running PYTHONPATH=. python -c "import foo; foo.f1(foo.B1()); foo.f2(foo.B2());" I obtain: f1() Traceback (most recent call last): File "<string>", line 1, in <module> Boost.Python.ArgumentError: Python argument types in foo.f2(B2) did not match C++ signature: f2(std::shared_ptr<A2>) Where is the problem? Cheers, Vaclav
On 04/20/2012 03:55 AM, VáclavŠmilauer wrote:
Hello,
I have a sample hierarchy of polymorphic classes (A from which B inherits). One of them (A1, B1) is managed with boost::shared_ptr, the other one (A2, B2) via std::shared_ptr (I defined the get_pointer template for std::shared_ptr).
When I call f1(boost::shared_ptr<A1>) with an object B1 from python, it is correctly upcast to the pointer to its base class and the c++ function is called. When I call f2(std::shared_ptr<A2>) with B2 argument from python, no upcasting takes place and I get Boost.Python.Argument error.
<snip>
Where is the problem?
I'm pretty sure this is a symptom of the fact that boost::shared_ptr is handled specially by Boost.Python, and custom smart pointers (which is what std::shared_ptr is considered in this case) don't have all the same features. In particular, Boost.Python doesn't assume that custom smart pointers have implicit upcast converters, which would be needed to do what you want (note that some smart pointers, like boost::scoped_ptr, don't have implicit upcast converters). The good news is that there's an easy workaround. You just need to tell Boost.Python that the implicit conversion exists: implicitly_convertible<std::shared_ptr<B2>,std::shared_ptr<A2>>(); That was enough to get your example to work for me. Jim
participants (2)
-
Jim Bosch -
Václav Šmilauer