Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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_ptrs. 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>?

share|improve this question

1 Answer 1

up vote 1 down vote accepted

Boost.Python needs to be aware that a smart pointer to Derived can be converted to a smart pointer to AbstractBase. This can be accomplished by either of the following:

  • Using boost::shared_ptr. Boost.Python has code to handle implicit conversions between boost::shared_ptrs when their element_type are hierarchical.
  • Register an implicit conversion from std::shared_ptr<Derived> to std::shared_ptr<AbstractBase> via boost::python::implicitly_convertible. std::shared_ptr meets the concept requirements for the implicitly_convertible, so it only requires registering the conversion in the module definition:

    implicitly_convertible<std::shared_ptr<Derived>,          // Source
                           std::shared_ptr<AbstractBase> >(); // Target
    
share|improve this answer
    
well,that's a little frustrating! I assumed that anything that worked for a boost::shared_ptr would work for a std::shared_ptr but I suppose this is just one of those edge cases we're gonna all have to deal with until everything is all nice and settled into C++11 –  A b May 31 '13 at 18:24

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.