How to work with 2D array returned from c function

2019-08-16 14:55发布

问题:

I have had success in sending numpy arrays to c functions with Cython. Whenever I have a function in c that takes int * and I have some variable in python, call itarr, that is 1D numpy array I just call the function with &arr[0] and it works.

Now I'm interested in receiving a 2D array created with a c function. How can I do this? Below is what I've tried.

// this is the c code that returns a 2D array
int **make_array() {
  int nrows = 3;
  int ncols = 5;

  int **ret = malloc(nrows * sizeof(int *));
  ret[0] = calloc(nrows * ncols, sizeof(int));
  for (int i = 1; i < nrows; i++) {
    ret[i] = ret[0] + i * ncols;
  }

  int count = 0;
  for (int i = 0; i < nrows; i++)
    for (int j = 0; j < ncols; j++)
      ret[i][j] = ++count;

  return ret;
}

python code

# python code that receives the 2D array
def foo():
    cdef int nRows = 3
    cdef int nCols = 5
    cdef int[:,::1] ret = np.zeros((nRows, nCols), dtype=np.int32)
    ret = make_array()

This gives me the following error for the last line of the function:

Cannot convert 'int **' to memoryviewslice

If I don't create a memoryview and instead have some variable created at the point of the call to receive the output the assignment to the variable will work fine. The problem is that I still can't figure out how to work with the returned value. For example I can't do this:

# python code that receives the 2D array
def foo():
    cdef int nRows = 3
    cdef int nCols = 5
    ret = make_array() # works
    print(ret) # fails

It complaints with the same error:

Cannot convert 'int **' to Python object

How can one work with int ** returned from a c function?

回答1:

As python is not capable of converting pointers from a C program I would rather advise you to use struct in your C code and then just return the struct by value like below:-

struct TDArray {
    int arr[3][3];
};

struct TDArray make_array() {
    struct TDArray numbers = {
        {
            {0, 1, 2},
            {3, 4, 5},
            {6, 7, 8}
        }
    };//I am hard coding it you just need utilize this approach in your code
            /* Something like
            struct TDArray numbers;
            numbers.arr[0][0]=0;
           */

    return numbers;
}

Hope this will help you.



标签: cython