用cython扩展numpy

时间:2009-12-22 03:32:20

标签: python numpy wrapping cython

我正在尝试包装一个包含许多函数的头文件

test.h

void test(int N, int* data_in, int* data_out);

这样我就可以使用numpy中的那些。

现在我有以下cython代码:

test.pyx

import numpy as np
cimport numpy as np

ctypedef np.int_t itype_t

cdef extern from 'VolumeForm.h':
    void _test 'test' (int, int*, int*)

def wrap_test(np.ndarray[itype_t, ndim=2] data):
    cdef np.ndarray[dtype_t, ndim=1] out
    out = np.zeros((data.shape[0],1), dtype=np.double)
    _test(
        data.shape[0],
        <itype_t*> data.data,
        <itype_t*> out.data
    )
    return out

但是,当我尝试编译它时,我收到错误:

Error converting Pyrex file to C:
(...)
Cannot assign type 'test.itype_t *' to 'int *'

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:4)

目前正在Cython邮件列表中讨论此问题;显然它源于一个Cython库中的一个小错误:

http://codespeak.net/mailman/listinfo/cython-dev

目前,一个潜在的解决方法是使用dtype np.long的NumPy数组,然后编写'ctypedef np.long_t itype_t'。然后你只需要使用长整数而不是整数来使C代码满意。

答案 1 :(得分:2)

另一种不需要您将int更改为long的解决方法:更改cdef extern from '...'块中的函数签名。 Cython仅使用cdef extern块中的声明来生成.c文件时检查类型,但生成的C代码只执行#include "VolumeForm.h",因此您可以使用它。

import numpy as np
cimport numpy as np

ctypedef np.int_t itype_t

cdef extern from 'VolumeForm.h':
    # NOTE: We changed the int* declarations to itype_t*
    void _test 'test' (int, itype_t*, itype_t*)

def wrap_test(np.ndarray[itype_t, ndim=2] data):
    cdef np.ndarray[dtype_t, ndim=1] out
    out = np.zeros((data.shape[0],1), dtype=np.double)
    _test(
        data.shape[0],
        <itype_t*> data.data,
        <itype_t*> out.data
    )
    return out

Cython不会抱怨上述情况。