I’m trying to read many values (in sequence) from a large numpy array using the C API. I’d like a more efficient way than seperately using boost::python::extract(…) on each value. Something like getting a pointer to the first value and then just incrementing that pointer.
I’ve read through the numpy API docs and I can see that it’s possible but am none the wiser on how to actually accomplish this. Can anyone point me to an example?
The Boost::Python API does not allow you to do that directly. You can use the Numpy C API to do it. Getting access to the underlying
PyObject*can be done using theptr()method ofboost::python::object. Access to the data can be obtained usingPyArray_DATA(PyObject*).Here’s an example that multiplies a 2d Numpy array by a number. I’ve had some trouble finding out how to compile this on Mac OS (i.e., where the Numpy headers are), so I’ll add this here: running
in Python gives the correct include path. You can for example use that in a cmake Find module (see this, for example; you’ll have to set the
PYTHON_EXECUTABLEvariable yourself).Update: I modified the code to handle the case in which the input array is not contiguous — this happens for example whenever you use a slice, as in
arr[::2, ::2]. The most straightforward way to handle this is to usePyArray_FROM_OTF; do note, however, that this will make a copy of the array unless the array is already in contiguous form. The advantage of this approach is that it can handle the case in which the input is any kind of nested sequence (e.g., a list of lists).If your array is so big that you would prefer avoiding making copies of it, you can use
PyArray_STRIDESto get the stride information that helps you access the data. From http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.strides.html,(note that this is the byte offset, so you should add it to the result of
PyArray_BYTESbefore you cast to final data type; also, this will not help if the array is improperly aligned, or if it has the wrong byte order)Here’s the sample code: