1

Trying to set up a dependency in C++ with a parent-child relationship. The parent contains the child and the child has a weak pointer to the parent.

I would also like to be able to derive from the parent in Python. However, when I do this, I get a weak pointer error connecting up this parent-child relationship.

C++ code:

#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

using namespace boost;
using namespace boost::python;

struct Child;

struct Parent : public enable_shared_from_this<Parent>
{
    void initialize();
    shared_ptr<Child> m_child;
};

struct Child: public enable_shared_from_this<Child>
{
    void setParent(shared_ptr<Parent> ptr);
    weak_ptr<Parent> m_parent;
};

void Parent::initialize()
{
    shared_ptr<Child> ptr(new Child);
    m_child = ptr;

    m_child->setParent(shared_from_this());
}

void Child::setParent(shared_ptr<Parent> ptr)
{
    m_parent = ptr;
}

static PyObject* create(PyObject* object)
{
    PyObject* instance = PyObject_CallObject(object, NULL);

    Parent* parent = extract<Parent*>(instance);
    parent->initialize();

    return instance;
}

Python binding:

BOOST_PYTHON_MODULE(test_module)
{
    class_<Parent>("Parent");

    def("create", &create);
} 

Python code:

from test_module import *

class Test(Parent):
    def __init__(self):
        Parent.__init__(self)

n = create(Test)

Error:

Traceback (most recent call last):
  File "main.py", line 8, in <module>
    n = create(Test)
RuntimeError: tr1::bad_weak_ptr

If I try and convert the extracted pointer to Parent into a shared_ptr, I get a free() invalid pointer error in Python.

Is there a way of getting round this problem or should I give up using weak pointers with Boost Python?

2 Answers 2

2

I played with the code without the python stuff.

This reproduced the problem:

Parent* p(new Parent);
p->initialize();

The problem is nothing is holding on to the shared_ptr object. This fixes it:

boost::shared_ptr<Parent> p(new Parent);
p->initialize();

Boost.Python FAQ : "When a shared_ptr is converted from Python, the shared_ptr actually manages a reference to the containing Python object. When a shared_ptr is converted back to Python, the library checks to see if it's one of those "Python object managers" and if so just returns the original Python object"

The Parent* needs to be stored in a shared_ptr somehow. I haven't figured out how yet.

Parent* parent = boost::python::extract<Parent*>(instance);
Sign up to request clarification or add additional context in comments.

Comments

1

The interface of class_ allows you to control how the object is held. It is a template parameter called HeldType. There is more information in the Boost.Python documentation on class_, but your Python binding might look more like this:

class_<Parent, boost::shared_ptr<Parent> >("Parent");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.