Have a pointer to the data. Need a Numpy array in Fortran order. Want to use Cython

This is a very common use case for me. I have a C function that returns me a double pointer:

//myheader.h double *mycfuntion(...) 

I know the sizes of the returned data. I also know that Fortran data is ordered. I want to write Cython "shim" to get the data in Python as a Numpy array:

 #myshim.pyx import numpy cimport numpy as cnumpy cnumpy.import_array() cdef extern from "myheader.h" : double *mycfunction(...) def mypyfunc(...) : cdef double *data = mycfunction(...) **MAGIC** return outarray 

MAGIC Ideas

(A) cdef cnumpy.ndarray[ cnumpy.double_t, mode='fortran', ...] outarray
That would be the most convenient way to do something. However, something critical that I'm missing here is how to turn the data pointer into a buffer that I can pass to the cnumpy.ndarray constructor. I tried:

 cdef cnumpy.ndarray[ cnumpy.double_t, mode='fortran', ...] outarray cdef bytes databuffer = <char *>data outarray = numpy.ndarray(buffer=databuffer, dtype=numpy.double, ...) 

This approach fails sequentially with TypeError: buffer is too small for requested array

(B) Nump C-API
I used cnumpy.PyArray_SimpleNewFromData(...) lot from Cython. It works great. The problem is that it does not support the flags argument, so I cannot tell it to build a Fortran array. An alternative that I used in pure C implementations is PyArray_NewFromDescr(...) . He accepts the flags. This approach is long and painful and means getting some characters from numpy through an extern block that has not yet been imported. There has to be a better way.


I searched my face for this problem, but nothing obvious came up. Maybe I'm an idiot. Or just sleep. Hooray!

+4
source share
1 answer

This is a bit hacky, but you can change the order of your measurements and then return the transpose. This should lead to the correctness of your step, but not to copy the data.

 cimport numpy as cnp cnp.import_array() cdef double a1[10] for i in range(10): a1[i] = i # C order a2 = cnp.PyArray_SimpleNewFromData(2, [2, 5], cnp.NPY_FLOAT64, a1) # fortran order a3 = cnp.PyArray_SimpleNewFromData(2, [5, 2], cnp.NPY_FLOAT64, a1).T # a2 and a3 point to the same data a2[0,0] = 10. print a2 print a3 
+2
source

Source: https://habr.com/ru/post/1384448/


All Articles