[C++-sig] create boost array from a Numpy PyArray without copying data?

Sebastian Walter walter at mathematik.hu-berlin.de
Tue Jan 20 10:27:02 CET 2009


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hey,
Thanks for the hint :),
Your code is a little to heavyweight for my purposes,
but I learned quite a lot how boost::python converters work.

And it also gave me the idea that finally solved my problem!
I don't have to convert the PyArray to boost::python::numeric::array
since the indirection over the boost array is presumably also
implemented as a converter (which basically undoes my wrapping, i guess).
So I figured, if that is the case, it should be possible to return the
PyArray directly.
And it does.
At least my test example works as wished:

- -------------------- test.cpp ----------------------------
#define PY_ARRAY_UNIQUE_SYMBOL PyArrayHandle
#include <iostream>
#include <boost/python.hpp>
#include <numpy/noprefix.h>

using namespace std;
using namespace boost;
using namespace boost::python;
using namespace boost::python::numeric;

// global to guarantee that the data is not freed after
test_function_that_doesnt_copy returns
double x[] = {1.,2.,3.};


// this function copies PyArray when the boost array constructor is called
array test_function_that_copies(){
	int N = 3;
	double x[] = {1.,2.,3.};
	array numpy_x(static_cast<array>(handle<>(PyArray_SimpleNewFromData(1,
&N, PyArray_DOUBLE, x))));
	double *y = static_cast<double*> PyArray_DATA(numpy_x.ptr());
	y[0] = 37.;

	for(int n = 0; n<N; ++n){
		cout<<"numpy_x[n]="<<y[n]<<"\t\t"<<"x[n]="<<x[n]<<endl;
	}
	return numpy_x;
}

// this function takes an existing pointer *x
// creates a Numpy PyArray from its data
// and returns the PyArray as PyObject
// Changes in Python result in changes of *x.
PyObject* test_function_that_doesnt_copy(){
	int N = 3;
	PyArrayObject *retval = (PyArrayObject*)PyArray_SimpleNewFromData(1,
&N, PyArray_DOUBLE, x);
	double *y = static_cast<double*> PyArray_DATA(retval);
	y[0] = 37.;

	for(int n = 0; n<N; ++n){
		cout<<"PyArray[n]="<<y[n]<<"\t\t"<<"x[n]="<<x[n]<<endl;
	}
	return (PyObject *)retval;
}


BOOST_PYTHON_MODULE(_test)
{
	import_array();
	array::set_module_and_type("numpy", "ndarray");
	def("test_function_that_copies", test_function_that_copies);
	def("test_function_that_doesnt_copy", test_function_that_doesnt_copy);
}


- --------------- test.py ------------------------
from _test import *

if __name__ == "__main__":
	print 'calling test_function_that_copies() from Python'
	test_function_that_copies()

	print 'calling test_function_that_doesnt_copy() from Python'
	test_function_that_doesnt_copy()

	print 'changing a value of *x from Python'
	y = test_function_that_doesnt_copy()
	y[1] = 54634.
	test_function_that_doesnt_copy()
	



- --------------- shell output --------------------
walter at wronski$ python test.py
calling test_function_that_copies() from Python
numpy_x[n]=37           x[n]=1
numpy_x[n]=2            x[n]=2
numpy_x[n]=3            x[n]=3
calling test_function_that_doesnt_copy() from Python
PyArray[n]=37           x[n]=37
PyArray[n]=2            x[n]=2
PyArray[n]=3            x[n]=3
changing a value of *x from Python
PyArray[n]=37           x[n]=37
PyArray[n]=2            x[n]=2
PyArray[n]=3            x[n]=3
PyArray[n]=37           x[n]=37
PyArray[n]=54634                x[n]=54634
PyArray[n]=3            x[n]=3

	


regards,
Sebastian



Ravi schrieb:
> On Monday 19 January 2009 07:16:10 Sebastian Walter wrote:
>> My question is:
>> How can I create a
>> boost::python::numeric::array from a Numpy Pyarray without copying data?
> 
> See http://mail.python.org/pipermail/cplusplus-sig/2008-October/013825.html 
> for a full solution. In particular, see the following class:
> 
> template <typename T> struct ublas_vector_from_numpy
> 
> Regards,
> Ravi
> 
> 
> 
> _______________________________________________
> Cplusplus-sig mailing list
> Cplusplus-sig at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.4-svn0 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org

iD8DBQFJdZjm9PBA5IG0h0ARAnEPAJ9yWG1AUu94qMGij3w9wvwboXYpEACeKA0N
fDFO2ev8dvaBmjbyQdvlSvk=
=SWB+
-----END PGP SIGNATURE-----


More information about the Cplusplus-sig mailing list