Passing numpy arrays in Cython to a C function that requires dynamically allocated arrays

I have a C code that has the following declaration:

int myfunc(int m, int n, const double **a, double **b, double *c);

So ais a constant 2D array, bis a 2D array, and cis a 1D array, all dynamically distributed. band cshould not be anything specific before they are transferred to myfuncand should be understood as output. For the purposes of this question, I am not allowed to modify the announcement myfunc.

Question 1: How to convert a given numpy array a_npto an array awith the format required by this C function so that I can call this C function in Cython with a?

Question 2: Are the declarations for band cbelow correct, or do they need to be in a different format so that the C function understands them as an array of 2D and 1D (respectively)?

My attempt:

myfile.pxd

cdef extern from "myfile.h":
    int myfunc(int p, int q, const double **a, double **b, double *c)

mytest.pyx

cimport cython
cimport myfile
import numpy as np
cimport numpy as np

p = 3
q = 4
cdef:
    double** a = np.random.random([p,q])
    double** b
    double* c

myfile.myfunc(p, q, a, b, c)

Then in iPython I launched

import pyximport; pyximport.install()
import mytest

The definition line agives an error message Cannot convert Python object to 'double **'. I do not get any error messages against bor c, but because I can not run a C function at this time, I'm not sure that the ads band cspelled correctly (that is, so that the C function can display 2D and 1D-array, respectively).

: , , myfunc . , myfunc.

+4
2

cython

double** numpy, - *.pyx . , , numpy . ( )

Fortran

C- fortran order ( x- , y , z- , a 3D-)

N,M = a.shape
# Make sure the array a has the correct memory layout (here F-order)
cdef np.ndarray[double, ndim=2, mode="fortran"] a_cython =
                         np.asarray(a, dtype = float, order="F")
#Create our helper array
cdef double** point_to_a = <double **>malloc(M * sizeof(double*))
if not point_to_a: raise MemoryError
try:
    #Fillup the array with pointers
    for i in range(M): 
        point_to_a[i] = &a_cython[0, i]
    # Call the C function that expects a double**
    myfunc(... &point_to_a[0], ...)
finally:
    free(point_to_a)

-

C- , C- ([x1, y1, z1] - , [x2, y2, z2] - ):

N,M = a.shape
# Make sure the array a has the correct memory layout (here C-order)
cdef np.ndarray[double, ndim=2, mode="c"] a_cython =
                         np.asarray(a, dtype = float, order="C")
#Create our helper array
cdef double** point_to_a = <double **>malloc(N * sizeof(double*))
if not point_to_a: raise MemoryError
try:
    for i in range(N): 
        point_to_a[i] = &a_cython[i, 0]
    # Call the C function that expects a double**
    myfunc(... &point_to_a[0], ...)
finally:
    free(point_to_a)
+4

1: NumPy Cython C, (. ).

2: , . NumPy cdef -ed.

cdef double[:,::1] a = np.random.random([p, q])
cdef double[:,::1] b = np.empty([p, q])
cdef double[::1] b = np.empty(q)

&a[0], , C. ::1 - .

: https://jakevdp.imtqy.com/blog/2012/08/08/memoryview-benchmarks/

, Cython Python, Python :

import pyximport; pyximport.install()
import mytest
mytest.mywrappedfunc()

mywrappedfunc - Python (def not cdef), , .

0

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


All Articles