简体   繁体   中英

Using Boost Python & std::shared_ptr

I'm trying to get Boost Python to play nicely with std::shared_ptr. Currently, I'm receiving this error:

Traceback (most recent call last):
  File "test.py", line 13, in <module>
    comp.place_annotation(circle.centre())
TypeError: No to_python (by-value) converter found for C++ type: std::shared_ptr<cgl::Anchor>

From calling circle.centre(), which returns an std::shared_ptr. I could change every std::shared_ptr to a boost::shared_ptr (which Boost Python plays nicely with) however the amount of code to change in pretty considerable and I'd like to use the standard library.

The circle method is declared like this:

const std::shared_ptr<Anchor> centre() const
{
    return Centre;
}

The anchor class like this:

class Anchor
{
    Point Where;
    Annotation* Parent;
public:

    Anchor(Annotation* parent) :
        Parent(parent)
    {
        // Do nothing.
    }

    void update(const Renderer& renderer)
    {
        if(Parent)
        {
            Parent->update(renderer);
        }
    }

    void set(Point point)
    {
        Where = point;
    }

    Point where() const
    {
        return Where;
    }
};

And the relevant Boost Python code is:

class_<Circle, bases<Annotation> >("Circle", init<float>())
.def("radius", &Circle::radius)
    .def("set_radius",  &Circle::set_radius)
    .def("diameter", &Circle::diameter)
    .def("top_left", &Circle::top_left)
    .def("centre", &Circle::centre);

// The anchor base class.
class_<Anchor, boost::noncopyable>("Anchor", no_init)
    .def("where", &Anchor::where);

I'm using Boost 1.48.0. Any ideas?

Looks like boost::python doesn't support C++ 11 std::shared_ptr.

If you have a look to file boost/python/converter/shared_ptr_to_python.hpp you'll find implementation of template function shared_ptr_to_python(shared_ptr<T> const& x) for boost::shared_ptr (it explain why the code works fine for boost::shared_ptr).

I think you have several options:

  • use boost::shared_ptr (which you trying to avoid)
  • write your implementation of shared_ptr_to_python for std::shared_ptr (IMHO the best option)
  • send request to boost::python developers to support std::shared_ptr

Unless I've misunderstood, I think this solves your problem:

boost::python::register_ptr_to_python<std::shared_ptr<Anchor>>();

http://www.boost.org/doc/libs/1_57_0/libs/python/doc/v2/register_ptr_to_python.html

There's a bug report for this: https://svn.boost.org/trac/boost/ticket/6545

Looks like someone is working on it.

A snippet from http://boost.2283326.n4.nabble.com/No-automatic-upcasting-with-std-shared-ptr-in-function-calls-td4573165.html :

/* make boost::python understand std::shared_ptr */
namespace boost {
       template<typename T>
       T *get_pointer(std::shared_ptr<T> p)
       {
               return p.get();
       }
}

Worked for me. You would define your classes like:

class_<foo, std::shared_ptr<foo>>("Foo", ...);

With this, other methods returning std::shared_ptr<foo> will Just Work.

Some magic may be required for virtual functions/polymorphism, that should be covered in the thread I linked to.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM