Boost Python Runtime error when passing object of derived type from python to C++ function expecting a shared_ptr to base type

独自空忆成欢 提交于 2019-11-30 09:49:17

问题


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


回答1:


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
    


来源:https://stackoverflow.com/questions/16853477/boost-python-runtime-error-when-passing-object-of-derived-type-from-python-to-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!