Chaining methods in C++ and Python
Here is a small test case which seems to reproduce the problem --- see attached files. Build test.so from test.cpp, then run python t.py Thanks! -- Alexey Goldin <Alexey.Goldin@jpl.nasa.gov>
Alexey Goldin <Alexey.Goldin@jpl.nasa.gov> writes:
Here is a small test case which seems to reproduce the problem --- see attached files.
Build test.so from test.cpp, then run python t.py
Thanks!
This is a simple issue of lifetime management. The C++ 'a' objects created in mk_tst are owned by their corresponding Python objects, which get destroyed when mk_tst exits. The pointers you have stored in your 'tst' object are dangling thereafter. The Introduction section at http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/*checkout*/boost/boost/libs/p... explains this fairly well HTH, -- Dave Abrahams Boost Consulting www.boost-consulting.com
This is a simple issue of lifetime management. The C++ 'a' objects created in mk_tst are owned by their corresponding Python objects, which get destroyed when mk_tst exits. The pointers you have stored in your 'tst' object are dangling thereafter.
The Introduction section at http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/*checkout*/boost/boost/libs/p... explains this fairly well
HTH,
Ok. This makes sense. However --- is it possible to do one of the following things in not too ugly way: 1) allow writing something like t.set_f1(a1).set_f2(a2) and make sure that pointers to both a1 and a2 are owned by t --- preferable solution 2) Making sure that t.set_f1(a1) does not return object of type tst, so calling t.set_f1(a1).set_f2(a2) and instead I have to call t.set_f1(a1) t.set_f2(a2) --- not so good, but at least making sure it is not easy to crash application? I can not change signature of method tst::set_f1 --- this is a library not under my control. Yes, I can write some wrappers but in my understanding this is what boost.python was created to avoid.... Thank you! boost.python is a wonderful tool, but sometimes as confusing as C++ :-) -- Alexey Goldin <Alexey.Goldin@jpl.nasa.gov>
Alexey Goldin <Alexey.Goldin@jpl.nasa.gov> writes:
This is a simple issue of lifetime management. The C++ 'a' objects created in mk_tst are owned by their corresponding Python objects, which get destroyed when mk_tst exits. The pointers you have stored in your 'tst' object are dangling thereafter.
The Introduction section at http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/*checkout*/boost/boost/libs/p... explains this fairly well
HTH,
Ok. This makes sense.
Agh, no it doesn't, sorry. I mis-analyzed the actual problem. The deal is that the result of t.set_f1(a1) looks like this: result t2 a1 +-------+ +-------+ +-------+ Python | tst +===>| tst +===>| a | +-------+ +-------+ +-------+ C++ | * | | tst | | a | +---+---+ +-------+ +-------+ | ^ +------------+ Where double arrows are ownership, and the single arrow represents the reference to the C++ object inside of t2. then, result.set_f2(a2) causes something like this: ++==========================++ result2 result1 || t2 a1 || a2 +-------+ +-------+|| +-------+ +-------+ || +-------+ Python | tst +===>| tst +++=>| tst +===>| a | ++==>| a | +-------+ +-------+ +-------+ +-------+ +-------+ C++ | * | | * | | tst | | a | | a | +---+---+ +---+---+ +-------+ +-------+ +-------+ | | ^ +----------->+------------+ As you can see the lifetime of a2 isn't maintained by t2 when it is returned. The key is to somehow get the set_f1() and set_f2() to return the original Python tst object instead of a "shadow". There are lots of ways to do that, but probably the easiest is to use back_reference<tst> in a thin wrapper function: object set_f1(back_reference<tst&> self, A & ff) { self.get().set_f1(ff); return self; }; ... .def("set_f1", set_f1, with_custodian_and_ward<1,2>() ) attached is a full demo. The question remains open as to whether Boost.Python should be doing something for you automatically here. I think return_internal_reference might include a test to see if it's the same object being returned, and handle this automatically.
However --- is it possible to do one of the following things in not too ugly way:
1) allow writing something like t.set_f1(a1).set_f2(a2) and make sure that pointers to both a1 and a2 are owned by t --- preferable solution
2) Making sure that t.set_f1(a1) does not return object of type tst, so calling t.set_f1(a1).set_f2(a2) and instead I have to call
t.set_f1(a1) t.set_f2(a2)
--- not so good, but at least making sure it is not easy to crash application?
I can not change signature of method tst::set_f1 --- this is a library not under my control. Yes, I can write some wrappers but in my understanding this is what boost.python was created to avoid....
Thank you! boost.python is a wonderful tool, but sometimes as confusing as C++ :-)
-- Alexey Goldin <Alexey.Goldin@jpl.nasa.gov>
_______________________________________________ C++-sig mailing list C++-sig@python.org http://mail.python.org/mailman/listinfo/c++-sig
-- Dave Abrahams Boost Consulting www.boost-consulting.com
Oh, this sounds good. Off to study manual.... Thanks a lot! On Wed, 2003-03-05 at 11:14, David Abrahams wrote:
There are lots of ways to do that, but probably the easiest is to use back_reference<tst> in a thin wrapper function:
object set_f1(back_reference<tst&> self, A & ff) { self.get().set_f1(ff); return self; };
participants (2)
-
Alexey Goldin -
David Abrahams