# [Numpy-discussion] blitz++ and numarray

Faheem Mitha faheem at email.unc.edu
Tue Mar 30 13:45:06 CST 2004

```On Mon, 29 Mar 2004, Fernando Perez wrote:

> The following should be enough to get you started:
>
> #include "Python.h"
> #include "Numeric/arrayobject.h"
> #include "blitz/array.h"
>
> using namespace std;
> using namespace blitz;
>
> // Convert a Numpy array to a blitz one, using the original's data (no copy)
> template<class T, int N>
> static Array<T,N> py_to_blitz(PyArrayObject* arr_obj)
> {
>      int T_size = sizeof(T);
>      TinyVector<int,N> shape(0);
>      TinyVector<int,N> strides(0);
>      int *arr_dimensions = arr_obj->dimensions;
>      int *arr_strides = arr_obj->strides;
>
>      for (int i=0;i<N;++i) {
>          shape[i]   = arr_dimensions[i];
>          strides[i] = arr_strides[i]/T_size;
>      }
>      return Array<T,N>((T*) arr_obj->data,shape,strides,neverDeleteData);
> }
>
> This is what I use for exactly the problem you are describing, and this code
> was pretty much lifted, with minor changes, from weave's auto-generated C++.
> What I do, to sidestep the memory management problems, is let python allocate
> all my Numeric arrays (using zeros() if I have no data).  I then use those
> inside my C++ code as blitz++ arrays via the above snippet.  Any changes made
> by the C++ code are automatically reflected in the Numeric arary, since the
> blitz object is using the Numeric data area.
>
> I hope this helps.  Let me know if you need more help, I can mail you complete
> example code.

Thanks. That is very helpful. I've incorporated this into my code, and
managed to get a simple example with boost working (extracting an element
of an array). See below.

Do you have a similar function which converts a blitz array to a
numarray/Numeric one? If not, I can easily concoct one for myself.

I now need to try to figure out what this reference counting stuff is
about. I read the official Python docs but am still currently very
confused.

Faheem.

***************************************************************************
#include "Python.h"
#include "Numeric/arrayobject.h"
#include <blitz/array.h>

using namespace std;
using namespace blitz;

template<class T, int N>
static Array<T,N> py_to_blitz(PyArrayObject* arr_obj);

static PyObject * arrmod_elem(PyObject *self, PyObject *args);

static PyMethodDef arrmod_methods[] =
{
{"elem", (PyCFunction)arrmod_elem, METH_VARARGS, "Returns the trace of a two-dimensional array.\n"},
{NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC initarrmod(void)
{
(void) Py_InitModule3("arrmod", arrmod_methods, "Returns the Trace of a two-dimensional array.\n");
import_array();
}

static PyObject * arrmod_elem(PyObject *self, PyObject *args)
{
PyObject *input, *result;
PyArrayObject *array;
double el;
int i, j;

if (!PyArg_ParseTuple(args, "Oii", &input, &i, &j))
return NULL;
array = (PyArrayObject *)
PyArray_ContiguousFromObject(input, PyArray_DOUBLE, 2, 2);
if (array == NULL)
return NULL;

Array<double,2> arr = py_to_blitz<double,2>(array);

el = arr(i,j);
result = Py_BuildValue("d",el);
return result;
}

// Convert a Numpy array to a blitz one, using the original's data (no
// copy)
template<class T, int N>
static Array<T,N> py_to_blitz(PyArrayObject* arr_obj)
{
int T_size = sizeof(T);
TinyVector<int,N> shape(0);
TinyVector<int,N> strides(0);
int *arr_dimensions = arr_obj->dimensions;
int *arr_strides = arr_obj->strides;

for (int i=0;i<N;++i)
{
shape[i]   = arr_dimensions[i];
strides[i] = arr_strides[i]/T_size;
}
return Array<T,N>((T*) arr_obj->data,shape,strides,neverDeleteData);
}

```