2

I've basically have a very simple node test case I'm trying to fix.

I have a simple Node class with a getChild and a getParent

The child can be assigned via the addChild function

Then this function automatically set the parent on the relevant class (so from the c++ side)

Unfortunately when I do that I lose the python reference..

I guess the code should be better to understand :

the basic main class MyNode:

class MyNode
{
public:
    MyNode(): m_name("unknown") {}
    MyNode(std::string name): m_name(name) {}
    MyNode(MyNode * const o) : m_name(o->m_name) {}
    virtual ~MyNode() {}

    std::string getName() const { return m_name; }
    void setName(std::string name) { m_name = name; }
    boost::shared_ptr<MyNode> getChild() const { return m_child; }
    const boost::shared_ptr<MyNode> & getParent() const { return m_parent; }

    void addChild(boost::shared_ptr<MyNode> node) {
        m_child = node;
        node->m_parent = boost::make_shared<MyNode>(this);
    }

private:
    std::string m_name;
    boost::shared_ptr<MyNode> m_parent;
    boost::shared_ptr<MyNode> m_child;
};

Then the boost python bindings code :

class_< MyNode, boost::shared_ptr<MyNode>/*, MyNodeWrapper*/ >("MyNode", init<std::string>())
    .add_property( "Name", &MyNode::getName, &MyNode::setName )
    .add_property( "Child", &MyNode::getChild )
    .add_property( "Parent", make_function(&MyNode::getParent, return_internal_reference<>()))
    .def( "addChild", &MyNode::addChild )
    ;

To finish my python test code :

>>> p=MyNode("p")
>>> o=MyNode("o")
>>> p.addChild(o)
>>> o.Parent
<hello_ext.MyNode object at 0x01C055A8>   << this is not equal to p
>>> p
<hello_ext.MyNode object at 0x01C06510>   << as you can see p here
>>> o.Parent
<hello_ext.MyNode object at 0x01C055A8>   << but at least the pointer doesn't change each time the Parent is called !
>>> p.Child == o                          << so for the child it works
True
>>> o.Parent == p                         << but it doeesn't work for Parent
False

The issue is certainly in the addFunction and how I use boost::make_shared to set the parent. I unfortunately have no idea what's going on.. I've tried to use a boost wrapper:

struct MyNodeWrapper : public MyNode, public boost::python::wrapper<MyNode>
{
    MyNodeWrapper( PyObject * a_PyObj ) : m_Self( a_PyObj ) {}
    MyNodeWrapper( PyObject * a_PyObj, const MyNode & a_Vec ) : MyNode( a_Vec ), m_Self( a_PyObj ) {}
    MyNodeWrapper( PyObject * a_PyObj, std::string name ) : MyNode( name ) , m_Self( a_PyObj ) {}

    PyObject * m_Self;
};

But still I'm not sure how I should modify the addChild function

Any idea ?

1 Answer 1

1

You can't do this:

    node->m_parent = boost::make_shared<MyNode>(this);

Without boost::enable_shared_from_this. See What is the usefulness of `enable_shared_from_this`?

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much ! I found another solution where I was using an external function.. something like this : void addChild(boost::shared_ptr<MyNode> pythis, boost::shared_ptr<MyNode> node) { pythis->m_child = node; node->m_parent = pythis; }
but your solution is way better.. so in case someone else has the same issue all you have to do is inherit from enable_shared_from_this then the addFunction can assign the parent pointer like that: node->m_parent = shared_from_this(); too easy and thanks again !

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.