[英]Importing C function with cython, how to pass a pointer to a python function
I'm trying to make a function which is defined in a C library callable from python.我正在尝试制作一个 function,它在 C 库中定义,可从 python 调用。 I'm begginer with cython n C
我是 cython n C 的初学者
Sooo in short I ended up having the following problem:简而言之,我最终遇到了以下问题:
#.pyx file
cdef extern from "lsd.h":
double *lsd_scale(int *n_out, double *img, int X, int Y, double scale)
def detector(int n_out, double img, int X, int Y, double scale):
return lsd_scale(n_out, img, X, Y, scale)
The definition from library.h file library.h 文件中的定义
@param n_out Pointer to an int where LSD will store the number of
line segments detected.
@param img Pointer to input image data. It must be an array of
doubles of size X x Y, and the pixel at coordinates
(x,y) is obtained by img[x+y*X].
@param X X size of the image: the number of columns.
@param Y Y size of the image: the number of rows.
@return A double array of size 7 x n_out, containing the list
of line segments detected. The array contains first
7 values of line segment number 1, then the 7 values
of line segment number 2, and so on, and it finish
by the 7 values of line segment number n_out.
The seven values are:
- x1,y1,x2,y2,width,p,-log10(NFA)
.
for a line segment from coordinates (x1,y1) to (x2,y2),
a width 'width', an angle precision of p in (0,1) given
by angle_tolerance/180 degree, and NFA value 'NFA'.
If 'out' is the returned pointer, the 7 values of
line segment number 'n+1' are obtained with
'out[7*n+0]' to 'out[7*n+6]'.
Soo in short the question is how to indicate in the python function that n_out is a pointer to an integer and img is a pointer to an array.简而言之,问题是如何在 python function 中指示 n_out 是指向 integer 的指针,而 img 是指向数组的指针。 I tried the following
我尝试了以下
ctypedef int*p_int
ctypedef double*p_double
cdef extern from "lsd.h":
double *lsd_scale(int *n_out, double *img, int X, int Y, double scale)
def detector(p_int n_out, p_double img, int X, int Y, double scale):
return lsd_scale(n_out, img, X, Y, scale)
But throws same error但抛出同样的错误
Error compiling Cython file:
------------------------------------------------------------
...
cdef extern from "lsd.h":
double *lsd_scale(int *n_out, double *img, int X, int Y, double scale)
def detector(int n_out, double img, int X, int Y, double scale):
return lsd_scale(n_out, img, X, Y, scale)
^
------------------------------------------------------------
detector.pyx:6:21: Cannot assign type 'int' to 'int *'
Error compiling Cython file:
------------------------------------------------------------
...
cdef extern from "lsd.h":
double *lsd_scale(int *n_out, double *img, int X, int Y, double scale)
def detector(int n_out, double img, int X, int Y, double scale):
return lsd_scale(n_out, img, X, Y, scale)
^
------------------------------------------------------------
detector.pyx:6:28: Cannot assign type 'double' to 'double *'
Error compiling Cython file:
------------------------------------------------------------
...
cdef extern from "lsd.h":
double *lsd_scale(int *n_out, double *img, int X, int Y, double scale)
def detector(int n_out, double img, int X, int Y, double scale):
return lsd_scale(n_out, img, X, Y, scale)
^
------------------------------------------------------------
Thanks for helping感谢您的帮助
The idea should be to create a useful Python interface, not directly reproduce the C interface.思路应该是创建一个有用的Python接口,而不是直接复制C接口。 Some of these arguments are pointless to the Python interface because they're already stored in (say) a Numpy array.
其中一些 arguments 对 Python 接口毫无意义,因为它们已经存储在(例如)Numpy 数组中。
double *img, int X, int Y
all describe the input array. double *img, int X, int Y
都描述了输入数组。 Essentially the requirement is "2D, contiguous block of memory".本质上,要求是“2D,连续的内存块”。 In Cython this can be expressed using a typed memoryview:
在 Cython 中,这可以使用类型化的 memoryview 来表达:
def detector(..., double[:,::1] img, ...):
... = lsd_scale(..., &img[0,0], # address of first element
img.shape[0], img.shape[1], # (it's possible these are the wrong way round, test!)
...)
The return value and n_out
combine to describe the output array, which is (7xn_out).返回值和
n_out
结合描述output数组,即(7xn_out)。 You could get Numpy to take ownership of this data , or you could copy the data.您可以让Numpy 获得此数据的所有权,或者您可以复制数据。 I recommend the latter.
我推荐后者。 Therefore, you don't actually want
n_out
to be an input from Python.因此,您实际上并不希望
n_out
成为 Python 的输入。 Instead:反而:
def detector(...):
cdef double[:,::1] result_memview # useful for later
cdef int n_out
cdef double* result = lsd_scale(&n_out, ...)
try:
# copy the data to an output array.
# The following is an untested outline. Making it work is an exercise for you
result_memview = <double[:7,:n_out:1]>result # make a temporary memoryview of the data
return np.array(result_memview) # should make a copy, I think
finally:
free(result) # cimported.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.