[C++-sig] Chaining methods in C++ and Python
David Abrahams
dave at boost-consulting.com
Wed Mar 5 20:14:49 CET 2003
Alexey Goldin <Alexey.Goldin at 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/python/doc/v2/with_custodian_and_ward.html#introduction
>> 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.
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: test.cpp
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20030305/08111300/attachment.txt>
-------------- next part --------------
> 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 at jpl.nasa.gov>
>
>
> _______________________________________________
> C++-sig mailing list
> C++-sig at python.org
> http://mail.python.org/mailman/listinfo/c++-sig
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
More information about the Cplusplus-sig
mailing list