[Boost.Python] newbie: Lifetime of objects
Hello everyone.
I'm trying to map into python classes shown below.
class A
{
friend class B;
public:
~A(void) {}
private:
A(B& b)
: m_B(&b)
{
}
B* m_B;
};
class B
{
friend class C;
public:
~B(void) {}
A* make_a(void)
{
return new A(*this);
}
private:
B(C& c)
: m_C(&c)
{
}
C* m_C;
};
class C
{
public:
~C(void) {}
B* make_b(void)
{
return new B(*this);
}
};
C* make_c()
{
return new C();
}
Objects are supposed to be created in the order C, B, A and destroyed
in the
order A, B, C.
I do not want to map constructors of A, B and C.
I can see three ways to do what I want:
1)
class_<A>("A", no_init);
class_<B>("B", no_init)
.def("make_a", &B::make_a, return_internal_reference<>())
;
class_<C>("C", no_init)
.def("make_b", &C::make_b, return_internal_reference<>())
;
def("make_c", make_c, return_value_policy
Sergey Sikorskiy
Hello everyone.
I'm trying to map into python classes shown below.
Sergey, The C++-sig (http://www.boost.org/more/mailing_lists.htm#cplussig) is usually a better place to get your Boost.Python questions answered.
class A { friend class B;
public: ~A(void) {}
private: A(B& b) : m_B(&b) { }
B* m_B; };
class B { friend class C;
public: ~B(void) {}
A* make_a(void) { return new A(*this); }
private: B(C& c) : m_C(&c) { }
C* m_C; };
class C { public: ~C(void) {}
B* make_b(void) { return new B(*this); } };
C* make_c() { return new C(); }
Objects are supposed to be created in the order C, B, A and destroyed in the order A, B, C. I do not want to map constructors of A, B and C. I can see three ways to do what I want:
1) class_<A>("A", no_init); class_<B>("B", no_init) .def("make_a", &B::make_a, return_internal_reference<>()) ;
Bad idea. That would only be appropriate if the resulting A object were internal to (and its lifetime managed by) the B object. It is not.
class_<C>("C", no_init) .def("make_b", &C::make_b, return_internal_reference<>()) ;
def("make_c", make_c, return_value_policy
());
Better. However, it doesn't account for the fact that the C object must exist as long as the B object does. You need to compose your return_value_policy with with_custodian_and_ward<0,1>.
2)
All three of these have the same problem.
class_<A>("A", no_init); class_<B>("B", no_init) .def("make_a", &B::make_a, return_value_policy
()) ;
THe part below is the same as what you proposed in #1.
class_<C>("C", no_init) .def("make_b", &C::make_b, return_value_policy
()) ; def("make_c", make_c, return_value_policy
());
I don't understand what you're trying to accomplish with noncopyable.
def("make_c", make_c, return_value_policy
()); C::make_b and B::make_a are supposed to return shared_ptr<B> and shared_ptr<A> respectively in this case.
That gets you off the hook for return_value_policy
After debugging this code I've got strange results: - In case 1 objects aren't get deleted at all; - In case 2 objects are get deleted in wrong order; - In case 3 objects are get deleted in wrong order;
Cases 2 and three seem to be identical to me. The only difference I can see is that in case 3 I should manage objects lifetime by myself from C++ code. In opposite, in case 2 objects lifetime will be managed by python.
I couldn't get an answer to my problem neither from documentation nor from Boost.Python tests nor from Google.
Any explanations or suggestions will be greatly appreciated.
Have you read http://www.boost.org/libs/python/doc/tutorial/doc/html/python/functions.html... -- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (2)
-
David Abrahams
-
Sergey Sikorskiy