Passing 3-dimensional numpy array to C

前端 未结 4 1014
旧巷少年郎
旧巷少年郎 2021-02-01 09:43

I\'m writing a C extension to my Python program for speed purposes, and running into some very strange behaviour trying to pass in a 3-dimensional numpy array. It works with a 2

4条回答
  •  北荒
    北荒 (楼主)
    2021-02-01 10:26

    According to http://docs.scipy.org/doc/numpy/reference/c-api.array.html?highlight=pyarray_ascarray#PyArray_AsCArray:

    Note The simulation of a C-style array is not complete for 2-d and 3-d arrays. For example, the simulated arrays of pointers cannot be passed to subroutines expecting specific, statically-defined 2-d and 3-d arrays. To pass to functions requiring those kind of inputs, you must statically define the required array and copy data.

    I think that this means that PyArray_AsCArray returns a block of memory with the data in it in C order. However, to access that data, more information is needed (see http://www.phy225.dept.shef.ac.uk/mediawiki/index.php/Arrays,_dynamic_array_allocation). This can either be achieved by knowing the dimensions ahead of time, declaring an array, and then copying the data in in the right order. However, I suspect that more general case is more useful: you don't know the dimensions until they are returned. I think that the following code will create the necessary C pointer framework to allow the data to be addressed.

    static PyObject* func(PyObject* self, PyObject* args) {
        PyObject *list2_obj;
        PyObject *list3_obj;
        if (!PyArg_ParseTuple(args, "OO", &list2_obj, &list3_obj)) return NULL;
    
        double **list2;
        double ***list3;
    
        // For the final version
        double **final_array2;
        double **final_array2;
    
        // For loops
        int i,j;
    
        //Create C arrays from numpy objects:
        int typenum = NPY_DOUBLE;
        PyArray_Descr *descr;
        descr = PyArray_DescrFromType(typenum);
    
        // One per array coming back ...
        npy_intp dims2[2];
        npy_intp dims3[3];
    
        if (PyArray_AsCArray(&list2_obj, (void **)&list2, dims2, 2, descr) < 0 || PyArray_AsCArray(&list3_obj, (void ***)&list3, dims3, 3, descr) < 0) {
            PyErr_SetString(PyExc_TypeError, "error converting to c array");
            return NULL;
        }
    
        // Create the pointer arrays needed to access the data
    
        // 2D array
        final_array2 = calloc(dim2[0], sizeof(double *));
        for (i=0; i

    I couldn't find a definition for npy_intp, the above assumes it is the same as int. If it isn't you will need to convert dim2 and dim3 into int arrays before doing the code.

提交回复
热议问题