Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/python/doc/v2/callbacks.txt @ 45

Last change on this file since 45 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 3.9 KB
Line 
1.. Copyright David Abrahams 2006. Distributed under the Boost
2.. Software License, Version 1.0. (See accompanying
3.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4
5Here's the plan:
6
7I aim to provide an interface similar to that of Boost.Python v1's
8callback<>::call(...) for dealing with callbacks. The interface will
9look like:
10
11    returning<ResultType>::call("method_name", self_object, a1, a2...);
12
13or
14
15    returning<ResultType>::call(callable_object, a1, a2...);
16
17ARGUMENT HANDLING
18
19There is an issue concerning how to make Python objects from the
20arguments a1...aN. A new Python object must be created; should the C++
21object be copied into that Python object, or should the Python object
22simply hold a reference/pointer to the C++ object? In general, the
23latter approach is unsafe, since the called function may store a
24reference to the Python object somewhere. If the Python object is used
25after the C++ object is destroyed, we'll crash Python.
26
27I plan to make the copying behavior the default, and to allow a
28non-copying behavior if the user writes boost::ref(a1) instead of a1
29directly. At least this way, the user doesn't get dangerous behavior "by
30accident". It's also worth noting that the non-copying ("by-reference")
31behavior is in general only available for class types, and will fail at
32runtime with a Python exception if used otherwise**
33
34However, pointer types present a problem: My first thought is to refuse
35to compile if any aN has pointer type: after all, a user can always pass
36*aN to pass "by-value" or ref(*aN) to indicate a pass-by-reference
37behavior. However, this creates a problem for the expected NULL pointer
38=> None conversion: it's illegal to dereference a null pointer value.
39
40We could use another construct, say "ptr(aN)", to deal with null
41pointers, but then what does it mean? We know what it does when aN is
42NULL, but it might either have by-value or by-reference behavior when aN
43is non-null.
44
45The compromise I've settled on is this:
46
471. The default behavior is pass-by-value. If you pass a non-null
48   pointer, the pointee is copied into a new Python object; otherwise
49   the corresponding Python argument will be None.
50
512. if you want by-reference behavior, use ptr(aN) if aN is a pointer
52   and ref(aN) otherwise. If a null pointer is passed to ptr(aN), the
53   corresponding Python argument will be None.
54
55RESULT HANDLING
56
57As for results, we have a similar problem: if ResultType is allowed to
58be a pointer or reference type, the lifetime of the object it refers to
59is probably being managed by a Python object. When that Python object is
60destroyed, our pointer dangles. The problem is particularly bad when the
61ResultType is char const* - the corresponding Python String object is
62typically uniquely-referenced, meaning that the pointer dangles as soon
63as returning<char const*>::call() returns.
64
65Boost.Python v1 deals with this issue by refusing to compile any uses of
66callback<char const*>::call(), but IMO this goes both too far and not
67far enough. It goes too far because there are cases where the owning
68String object survives beyond the call (just for instance when it's the
69name of a Python class), and it goes not far enough because we might
70just as well have the same problem with any returned pointer or
71reference.
72
73I propose to address this in Boost.Python v2 by
74
75    1. lifting the compile-time restriction on const
76    char* callback returns
77
78    2. detecting the case when the reference count on the
79    result Python object is 1 and throwing an exception
80    inside of returning<U>::call() when U is a pointer or
81    reference type.
82
83I think this is acceptably safe because users have to explicitly specify
84a pointer/reference for U in returning<U>, and they will be protected
85against dangles at runtime, at least long enough to get out of the
86returning<U>::call() invocation.
87
88-Dave
89
90**It would be possible to make it fail at compile-time for non-class
91types such as int and char, but I'm not sure it's a good idea to impose
92this restriction yet.
Note: See TracBrowser for help on using the repository browser.