Cython memoryviews:用数组参数包装 c 函数以传递 numpy 数组
Cython memoryviews: wrapping c function with array parameter to pass numpy array
我正在尝试使用 Cython 用数组参数 (quick_sort()
) 包装 c 函数,这样我就可以将一个 numpy 数组传递给它。我已经在文档、SO 和 Web 上搜索了一个有效的最小示例,但没有找到。我尝试了几种可能性但没有任何进展,所以请帮我弄清楚。这是我的文件:
quicksort.c
#include <stdio.h>
void quick_sort (int* a, int n) {
int i, j, p, t;
if (n < 2)
return;
p = a[n / 2];
for (i = 0, j = n - 1;; i++, j--) {
while (a[i] < p)
i++;
while (p < a[j])
j--;
if (i >= j)
break;
t = a[i];
a[i] = a[j];
a[j] = t;
}
quick_sort(a, i);
quick_sort(a + i, n - i);
}
quicksort.h
void quick_sort (int* a, int n);
quicksort.pxd
cdef extern from "quicksort.h":
void quick_sort (int[:] a, int n)
cy_quicksort.pyx
cimport quicksort
def quicksort_c(int[:] a):
quicksort.quick_sort(a, a.size)
setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(
name='quicksort cython',
ext_modules=cythonize("*.pyx"),
)
当我运行宁python setup.py build_ext --inplace
命令时,它returns出现以下错误:
cy_quicksort.c:1362:14: error: passing '__Pyx_memviewslice' to parameter of
incompatible type 'int *'
quick_sort(__pyx_v_a, __pyx_t_3);
^~~~~~~~~
./quicksort.h:1:23: note: passing argument to parameter 'a' here
void quick_sort (int* a, int n);
我想要实现的是编译它并能够 运行 例如:
import numpy as np
from cy_quicksort import quicksort_c
a = np.array(range(9, 0, -1), dtype=np.int32)
quicksort_c(a)
提前感谢您的宝贵时间!
编辑:
根据 DavidW 在 quicksort.pxd、cy_quicksort.pyx 中建议的更改并更改 setup.py 将文件转换为以下形式,它按预期工作。
setup.py
from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
sourcefiles = ['cy_quicksort.pyx', 'quicksort.c']
extensions = [Extension("cy_quicksort", sourcefiles)]
setup(
ext_modules = cythonize(extensions)
)
问题主要在"quicksort.pxd" - 定义需要与quicksort.h中的定义相匹配:
cdef extern from "quicksort.h":
void quick_sort (int* a, int n)
([:]
将其定义为内存视图,这是 Cythony 的发明,不能直接转换为指针,正如您的错误所说)。
然后您需要从 "cy_quicksort.pyx"
中的内存视图中获取指针
def quicksort_c(int[::1] a):
quicksort.quick_sort(&a[0], a.size) # get address of first element
我已经将输入参数更改为 [::1]
以指定元素在内存中必须是连续的,我认为这是快速排序所期望的。
(注意 - 未经测试,但相当简单,应该可以!)
我正在尝试使用 Cython 用数组参数 (quick_sort()
) 包装 c 函数,这样我就可以将一个 numpy 数组传递给它。我已经在文档、SO 和 Web 上搜索了一个有效的最小示例,但没有找到。我尝试了几种可能性但没有任何进展,所以请帮我弄清楚。这是我的文件:
quicksort.c
#include <stdio.h>
void quick_sort (int* a, int n) {
int i, j, p, t;
if (n < 2)
return;
p = a[n / 2];
for (i = 0, j = n - 1;; i++, j--) {
while (a[i] < p)
i++;
while (p < a[j])
j--;
if (i >= j)
break;
t = a[i];
a[i] = a[j];
a[j] = t;
}
quick_sort(a, i);
quick_sort(a + i, n - i);
}
quicksort.h
void quick_sort (int* a, int n);
quicksort.pxd
cdef extern from "quicksort.h":
void quick_sort (int[:] a, int n)
cy_quicksort.pyx
cimport quicksort
def quicksort_c(int[:] a):
quicksort.quick_sort(a, a.size)
setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(
name='quicksort cython',
ext_modules=cythonize("*.pyx"),
)
当我运行宁python setup.py build_ext --inplace
命令时,它returns出现以下错误:
cy_quicksort.c:1362:14: error: passing '__Pyx_memviewslice' to parameter of
incompatible type 'int *'
quick_sort(__pyx_v_a, __pyx_t_3);
^~~~~~~~~
./quicksort.h:1:23: note: passing argument to parameter 'a' here
void quick_sort (int* a, int n);
我想要实现的是编译它并能够 运行 例如:
import numpy as np
from cy_quicksort import quicksort_c
a = np.array(range(9, 0, -1), dtype=np.int32)
quicksort_c(a)
提前感谢您的宝贵时间!
编辑:
根据 DavidW 在 quicksort.pxd、cy_quicksort.pyx 中建议的更改并更改 setup.py 将文件转换为以下形式,它按预期工作。
setup.py
from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
sourcefiles = ['cy_quicksort.pyx', 'quicksort.c']
extensions = [Extension("cy_quicksort", sourcefiles)]
setup(
ext_modules = cythonize(extensions)
)
问题主要在"quicksort.pxd" - 定义需要与quicksort.h中的定义相匹配:
cdef extern from "quicksort.h":
void quick_sort (int* a, int n)
([:]
将其定义为内存视图,这是 Cythony 的发明,不能直接转换为指针,正如您的错误所说)。
然后您需要从 "cy_quicksort.pyx"
中的内存视图中获取指针def quicksort_c(int[::1] a):
quicksort.quick_sort(&a[0], a.size) # get address of first element
我已经将输入参数更改为 [::1]
以指定元素在内存中必须是连续的,我认为这是快速排序所期望的。
(注意 - 未经测试,但相当简单,应该可以!)