In general, raw pointers passed to or returned from functions are problematic for Boost.Python because pointers have too many potential meanings. Is it an iterator? A pointer to a single element? An array? When used as a return value, is the caller expected to manage (delete) the pointed-to object or is the pointer really just a reference? If the latter, what happens to Python references to the referent when some C++ code deletes it?
There are a few cases in which pointers are converted automatically:
const char*
are interpreted as
null-terminated 'C' strings and when passed to or returned from C++ functions are
converted from/to Python strings.
My first piece of advice to anyone with a case not covered above is
``find a way to avoid the problem.'' For example, if you have just one
or two functions that return a pointer to an individual const
T
, and T
is a wrapped class, you may be able to write a ``thin
converting wrapper'' over those two functions as follows:
const Foo* f(); // original function const Foo& f_wrapper() { return *f(); } ... my_module.def(f_wrapper, "f");
Foo must have a public copy constructor for this technique to work, since Boost.Python
converts const T&
values to_python
by copying the T
value into a new extension instance.
The first step in handling the remaining cases is to figure out what the pointer means. Several potential solutions are provided in the examples that follow:
If you have lots of functions returning a const T*
for some
wrapped T
, you may want to provide an automatic
to_python
conversion function so you don't have to write lots of
thin wrappers. You can do this simply as follows:
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround PyObject* to_python(const Foo* p) { return to_python(*p); // convert const Foo* in terms of const Foo& } BOOST_PYTHON_END_CONVERSION_NAMESPACE
If the wrapped type doesn't have a public copy constructor, if copying is extremely costly (remember, we're dealing with Python here), or if the pointer is non-const and you really need to be able to modify the referent from Python, you can use the following dangerous trick. Why dangerous? Because python can not control the lifetime of the referent, so it may be destroyed by your C++ code before the last Python reference to it disappears:
This will cause the Foo* to be treated as though it were an owning smart pointer, even though it's not. Be sure you don't use the reference for anything from Python once the pointer becomes invalid, though. Don't worry too much about theBOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround PyObject* to_python(Foo* p) { return boost::python::python_extension_class_converters<Foo>::ptr_to_python(p); } PyObject* to_python(const Foo* p) { return to_python(const_cast<Foo*>(p)); } BOOST_PYTHON_END_CONVERSION_NAMESPACE
const_cast<>
above: Const-correctness is completely lost
to Python anyway!
If you have an interface that uses non-const pointers (or references) as in/out parameters to types which in Python are immutable (e.g. int, string), there simply is no way to get the same interface in Python. You must resort to transforming your interface with simple thin wrappers as shown below:
const void f(int* in_out_x); // original function const int f_wrapper(int in_x) { f(in_x); return in_x; } ... my_module.def(f_wrapper, "f");
Of course, [in/]out parameters commonly occur only when there is already a return value. You can handle this case by returning a Python tuple:
typedef unsigned ErrorCode; const char* f(int* in_out_x); // original function ... #include <boost/python/objects.hpp> const boost::python::tuple f_wrapper(int in_x) { const char* s = f(in_x); return boost::python::tuple(s, in_x); } ... my_module.def(f_wrapper, "f");
Now, in Python:
>>> str,out_x = f(3)
© Copyright David Abrahams 2000. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.
Updated: Nov 26, 2000