18

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?

Morwenn
  • 21,684
  • 12
  • 93
  • 152
Liam M
  • 5,306
  • 4
  • 39
  • 55

4 Answers4

17

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
Dmitriy
  • 3,305
  • 7
  • 44
  • 55
  • https://github.com/boostorg/python/issues/29 There is an open ticket related to supporting std::shard_ptr. – maxywb Feb 22 '16 at 17:39
  • how can we delete the above declaration of the shared_ptr. Suppose, i have shared_ptr > net; i want to empty the data in net at end of program. Any help regarding this will be helpful. Thank you – Sai krishna Jun 20 '19 at 10:21
6

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

cdyson37
  • 7,828
  • 3
  • 24
  • 16
1

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

Looks like someone is working on it.

jhasse
  • 2,379
  • 1
  • 30
  • 40
1

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.

Vegard
  • 2,081
  • 1
  • 17
  • 26