Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typecasting PyArrayObject data to a C array

I want to work with my Numpy arrays in a C extension. Many examples in this case uses the structure of PyArrayObject,

array->data , array->strides[0] , array->strides[1] , ...

pointers in order to reach the data, if I wanted to reach my array in a more familiar (or tidier) way to me, with indices like

array[i][j]

how should I proceed so? Should I typecast (bool *) array->data and work with the C array I created? (my elements are bools)

My function declaration for now is (not finished, of course)

static PyObject *
xor_masking(PyObject *self, PyObject *args)
{

PyObject *input;
PyObject *mask;
PyObject *adjacency;
PyObject *state;
PyArrayObject *arr_mask;
PyArrayObject *arr_adjacency;
PyArrayObject *arr_state;
PyArrayObject *arr_next_state;

double sum;
int counter_node, n_nodes;

/*  PyArg_ParseTuple
 *  checks if from args, the pointers of type "O" can be extracted, and extracts them
 */

if (!PyArg_ParseTuple(args, "OOO:xor_masking_C", &mask, &adjacency, &state))
    return NULL;

/*
 *  The pointer returned by PyArray_ContiguousFromObject is typecasted to
 *  a PyArrayObject Pointer and array is pointed to the same address.
 */

arr_mask = (PyArrayObject *)
PyArray_ContiguousFromObject(mask, PyArray_BOOL, 2, 2);
arr_adjacency = (PyArrayObject *)
PyArray_ContiguousFromObject(adjacency, PyArray_BOOL, 2, 2);
arr_state = (PyArrayObject *)
PyArray_ContiguousFromObject(state, PyArray_BOOL, 2, 2);

if (array == NULL)
    return NULL;

int n_mask_0 = mask->dimensions[0];
int n_mask_1 = mask->dimensions[1];
int n_adjacency_0 = adjacency->dimensions[0];
int n_adjacency_1 = adjacency->dimensions[1];
int n_state_0 = state->dimensions[0];
int n_nodes = n_state_0;
/*
 * if the dimensions don't match, return NULL
 */

bool c_mask[n_nodes][n_nodes];

if (n_mask_0 != n_mask_1 || n_adjacency_0 != n_adjacency_1 ||
n_adjacency_0 != n_mask_0 || n_adjacency_0 != n_adjacency_1) {
    return NULL;
}

/*
 *    The 2D arrays are introduced as follows
 *    array[i][j] = (array->data + i*array->strides[0] + j*array->strides[1])
 */

for (counter_node = 0; i < n_mask; i++){
    *row_start = (array->data + i*array->strides[0]);
}


//Py_DECREF();

//return PyFloat_FromDouble();
}

Thanks!

like image 443
mehmet.ali.anil Avatar asked Oct 12 '11 17:10

mehmet.ali.anil


3 Answers

I'm not sure if this answers your question but, to reach your NumPy data in C, you could try to create an iterator to loop over your array in C. It doesn't give you indexing you're after ([i][j]) but it covers the entire array

static PyObject *func1(PyObject *self, PyObject *args) {
    PyArrayObject *X;
    int ndX;
    npy_intp *shapeX;
    NpyIter *iter;
    NpyIter_IterNextFunc *iternext;
    PyArray_Descr *dtype;
    double **dataptr;

    PyArg_ParseTuple(args, "O!", &PyArray_Type, &X);
    ndX = PyArray_NDIM(X);
    shapeX = PyArray_SHAPE(X);
    dtype = PyArray_DescrFromType(NPY_DOUBLE);
    iter = NpyIter_New(X, NPY_ITER_READONLY, NPY_KEEPORDER, NPY_NO_CASTING, dtype);
    iternext = NpyIter_GetIterNext(iter, NULL);
    dataptr = (double **) NpyIter_GetDataPtrArray(iter);
    do {
        cout << **dataptr << endl; //Do something with the data in your array
    } while (iternext(iter));   
    NpyIter_Deallocate(iter);
    return Py_BuildValue(...);
}
like image 60
Joel Vroom Avatar answered Nov 16 '22 03:11

Joel Vroom


I think you'll want to look at this: http://docs.scipy.org/doc/numpy/reference/c-api.array.html

In particular,

void* PyArray_GETPTR3(PyObject* obj, <npy_intp> i, <npy_intp> j, <npy_intp> k)

and friends. Those are the functions that David Heffernan would be surprised if the API didn't provide.

like image 25
Ben Avatar answered Nov 16 '22 03:11

Ben


This should help you.

http://mail.scipy.org/pipermail/numpy-discussion/2003-November/014837.html

like image 38
Prayag Avatar answered Nov 16 '22 03:11

Prayag