Cython MemoryViews:使用数组参数包装C函数以传递numpy数组 [英] Cython memoryviews: wrapping c function with array parameter to pass numpy array

查看:131
本文介绍了Cython MemoryViews:使用数组参数包装C函数以传递numpy数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Cython用数组参数( quick_sort())包装c函数,因此可以将numpy数组传递给它。我已经在文档,SO和网络中搜索了一个可行的最小示例,但没有找到。我尝试了几种可能性,但没有任何进展,因此请帮助我解决这个问题。这是我的文件:


quicksort.c

  #include< stdio.h> 

void quick_sort(int * a,int n){
int i,j,p,t;
,如果(n <2)
回报;
p = a [n / 2];
for(i = 0,j = n-1 ;; i ++,j--){
而(a [i]< p)
i ++;
而(p j--;
如果(i> = j)
休息;
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来自 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)

设置。 py

 来自distutils.core导入设置,来自Cython的
。构建导入cythonize

的设置(
name ='quicksort cython',
ext_modules = cythonize( *。pyx),

当我运行 python setup.py build_ext --inplace 命令时,它返回以下错误:

  cy_quicksort.c:1362:14:错误:将'__Pyx_memviewslice'传递给
不兼容类型'int *'
quick_sort(__ pyx_v_a,__pyx_t_3)的参数;
^ ~~~~~~~~
./quicksort.h:1:23:注意:在此处将参数传递给参数'a'
void quick_sort(int * a,int n );

我要实现的是对此进行编译并能够运行:

 从cy_quicksort导入numpy作为np 
导入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


从distutils.core导入设置
从cyutil.com中的

 。从distutils.extension导入import cythonize 
'cy_quicksort.pyx','quicksort.c']

扩展名= [Extension( cy_quicksort,源文件)]

setup(
ext_modules = cythonize (扩展名)


解决方案

问题主要出在 quicksort.pxd-定义需要与quicksort.h中的匹配:

  cdef extern from quicksort.h:
void quick_sort(int * a,int n)

(< [:] 而是将其定义为memoryview,这是Cythony的发明,不能直接转换为指针,如您的错误所述)。 / p>

然后您需要从 cy_quicksort.pyx中的内存视图中获取一个指针

  def quicksort_c(int [:: 1] a):
quicksort.quick_sort(& a [0],a.size)#获取第一个元素的地址

我将输入参数更改为 [:: 1] 来指定元素必须在内存中是连续的,我认为这是quicksort所期望的。



(注意-未经测试,但是相当简单,应该可以使用!)


I am trying to use Cython to wrap c function with an array parameter (quick_sort()), so I can pass a numpy array to it. I've searched the documentation, SO and web for a working, minimal example but didn't find it. I've tried several possibilities but without any progress, so please help me to figure it out. Here are my files:

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"),
)

When I'm running python setup.py build_ext --inplace command, it returns the following error:

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);

What I want to achieve is to compile this and be able to run for example:

import numpy as np
from cy_quicksort import quicksort_c
a = np.array(range(9, 0, -1), dtype=np.int32)
quicksort_c(a)

Thanks in advance for Your time!


Edit:

After changes suggested by DavidW in quicksort.pxd, cy_quicksort.pyx and changing the setup.py file into the following form, it's working as intended.

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)
)

解决方案

The problem is mainly in "quicksort.pxd" - the definition needs to match that in quicksort.h:

cdef extern from "quicksort.h":
    void quick_sort (int* a, int n)

([:] defines it as a memoryview instead, which is a Cythony invention and can't be cast directly to a pointer, as your error says).

You then need to get a pointer from the memoryview in "cy_quicksort.pyx"

def quicksort_c(int[::1] a):
    quicksort.quick_sort(&a[0], a.size) # get address of first element

I've changed the input parameter to [::1] to specify that the elements must be continuous in memory, which I think is what quicksort expects.

(Note - untested, but reasonably simple so should work!)

这篇关于Cython MemoryViews:使用数组参数包装C函数以传递numpy数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆