[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