[C++-sig] Moving "decorator" into C++ part of module
Albert Strasheim
fullung at gmail.com
Thu Jul 12 16:21:36 CEST 2007
Hello
On Thu, 12 Jul 2007, Matthieu Brucher wrote:
> Sorry to unearth this thread, but I'd like convert numpy array as well, but
> not only for matrices (my lab uses multi-dimensional images in C++ and it
> could be great to have a non-copying wrapper to Python and from Python).
> I'm very new to Boost.Python and to the numpy C-API, I hope I'll not ask
> stupid questions.
>
> In your code, Albert, you wrap a uBlas matrix in array_struct__. Is there
> some kind of reference counting for the memory allocated in the matrix ? Or
> the matrix must be valid until the python variable is destroyed ?
> If this is the case, is there a "simple" way of using smart pointers (if the
> class that must be wrapped uses smart pointers for holding the data) ?
The allocation and deallocation of the array is still managed by
Boost.Python. You control the management through using the existing
Boost.Python call policies.
I put it together as follows:
1. The type you want to wrap should expose an __array_struct__. See,
for example, my ublas_matrix wrapper:
http://pyspkrec.googlecode.com/svn/trunk/numpycpp/ublas_matrix.h
and you might want to look at the documentation for the array interface:
http://numpy.scipy.org/array_interface.shtml
For your multidimensional image class you want want to be more fancy and
put something useful in descr. I think you could use this to make your
image object behave like a NumPy record array, for example.
2. Functions returning your type are wrapped with return_asarray
combined with any Boost.Python call policy, like here:
http://pyspkrec.googlecode.com/svn/trunk/numpycpp/src/ublas_matrix_test.cpp
so you do something like:
def("foo", &foo, return_asarray<py::return_value_policy<py::manage_new_object> >());
where py == boost::python.
3. return_asarray is defined here:
http://pyspkrec.googlecode.com/svn/trunk/numpycpp/numpycpp.h
To understand how it works, you should study the CallPolicies concept:
http://www.boost.org/libs/python/doc/v2/CallPolicies.html#CallPolicies-concept
What I'm doing is apparently called CallPolicies composition.
The line:
result = BasePolicy_::postcall(args_, result);
gets the PyObject* of the wrapped object which might in turn already be
wrapped in some Boost.Python thingy (like a custodian with ward). This
object exposes __array_struct__, which is read when we pass it on to
NumPy C/API function:
return PyArray_FromStructInterface(result);
Take a look at that function's source to get a better idea of what
it does. This function returns a NumPy array that owns a reference (if
that's the right terminology?) to the wrapped object.
My tests seem to indicate that this all does what I think it does, but
I could be wrong. ;-)
Good luck with your wrapping and feel free to contact me if you have
any more issues or questions.
Cheers,
Albert
More information about the Cplusplus-sig
mailing list