[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

Hash: SHA1

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){
	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){
	return (PyObject *)retval;

	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'

	print 'calling test_function_that_doesnt_copy() from Python'

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

- --------------- 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



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

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


More information about the Cplusplus-sig mailing list