callbacks.txt
来自「Boost provides free peer-reviewed portab」· 文本 代码 · 共 93 行
TXT
93 行
.. Copyright David Abrahams 2006. Distributed under the Boost.. Software License, Version 1.0. (See accompanying.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)Here's the plan:I aim to provide an interface similar to that of Boost.Python v1'scallback<>::call(...) for dealing with callbacks. The interface willlook like: returning<ResultType>::call("method_name", self_object, a1, a2...);or returning<ResultType>::call(callable_object, a1, a2...);ARGUMENT HANDLINGThere is an issue concerning how to make Python objects from thearguments a1...aN. A new Python object must be created; should the C++object be copied into that Python object, or should the Python objectsimply hold a reference/pointer to the C++ object? In general, thelatter approach is unsafe, since the called function may store areference to the Python object somewhere. If the Python object is usedafter the C++ object is destroyed, we'll crash Python.I plan to make the copying behavior the default, and to allow anon-copying behavior if the user writes boost::ref(a1) instead of a1directly. At least this way, the user doesn't get dangerous behavior "byaccident". It's also worth noting that the non-copying ("by-reference")behavior is in general only available for class types, and will fail atruntime with a Python exception if used otherwise**However, pointer types present a problem: My first thought is to refuseto compile if any aN has pointer type: after all, a user can always pass*aN to pass "by-value" or ref(*aN) to indicate a pass-by-referencebehavior. However, this creates a problem for the expected NULL pointer=> None conversion: it's illegal to dereference a null pointer value.We could use another construct, say "ptr(aN)", to deal with nullpointers, but then what does it mean? We know what it does when aN isNULL, but it might either have by-value or by-reference behavior when aNis non-null.The compromise I've settled on is this: 1. The default behavior is pass-by-value. If you pass a non-null pointer, the pointee is copied into a new Python object; otherwise the corresponding Python argument will be None.2. if you want by-reference behavior, use ptr(aN) if aN is a pointer and ref(aN) otherwise. If a null pointer is passed to ptr(aN), the corresponding Python argument will be None.RESULT HANDLINGAs for results, we have a similar problem: if ResultType is allowed tobe a pointer or reference type, the lifetime of the object it refers tois probably being managed by a Python object. When that Python object isdestroyed, our pointer dangles. The problem is particularly bad when theResultType is char const* - the corresponding Python String object istypically uniquely-referenced, meaning that the pointer dangles as soonas returning<char const*>::call() returns.Boost.Python v1 deals with this issue by refusing to compile any uses ofcallback<char const*>::call(), but IMO this goes both too far and notfar enough. It goes too far because there are cases where the owningString object survives beyond the call (just for instance when it's thename of a Python class), and it goes not far enough because we mightjust as well have the same problem with any returned pointer orreference.I propose to address this in Boost.Python v2 by 1. lifting the compile-time restriction on const char* callback returns 2. detecting the case when the reference count on the result Python object is 1 and throwing an exception inside of returning<U>::call() when U is a pointer or reference type.I think this is acceptably safe because users have to explicitly specifya pointer/reference for U in returning<U>, and they will be protectedagainst dangles at runtime, at least long enough to get out of thereturning<U>::call() invocation.-Dave**It would be possible to make it fail at compile-time for non-classtypes such as int and char, but I'm not sure it's a good idea to imposethis restriction yet.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?