将numpy整数数组传递给c代码

将numpy整数数组传递给c代码,numpy,cython,python-extensions,Numpy,Cython,Python Extensions,我正在尝试编写Cython代码,以比sklearn的内置代码更快地将密集特征矩阵、目标向量对转储为libsvm格式。我得到一个编译错误,抱怨将目标向量(int的numpy数组)传递给相关的c函数时出现了类型问题 代码如下: import numpy as np cimport numpy as np cimport cython cdef extern from "cdump.h": int filedump( double features[], int numexemplars,

我正在尝试编写Cython代码,以比sklearn的内置代码更快地将密集特征矩阵、目标向量对转储为libsvm格式。我得到一个编译错误,抱怨将目标向量(int的numpy数组)传递给相关的c函数时出现了类型问题

代码如下:

import numpy as np
cimport numpy as np
cimport cython

cdef extern from "cdump.h":
    int filedump( double features[], int numexemplars, int numfeats, int target[], char* outfname)

@cython.boundscheck(False)
@cython.wraparound(False)
def fastdumpdense_libsvmformat(np.ndarray[np.double_t,ndim=2] X, y, outfname):
    if X.shape[0] != len(y):
        raise ValueError("X and y need to have the same number of points")

    cdef int numexemplars = X.shape[0]
    cdef int numfeats = X.shape[1]

    cdef bytes py_bytes = outfname.encode()
    cdef char* outfnamestr = py_bytes

    cdef np.ndarray[np.double_t, ndim=2, mode="c"] X_c
    cdef np.ndarray[np.int_t, ndim=1, mode="c"] y_c
    X_c = np.ascontiguousarray(X, dtype=np.double)
    y_c = np.ascontiguousarray(y, dtype=np.int)
    retval = filedump( &X_c[0,0], numexemplars, numfeats, &y_c[0], outfnamestr)

    return retval
当我试图使用distutils编译这段代码时,我得到了错误

cythoning fastdump_svm.pyx to fastdump_svm.cpp

Error compiling Cython file:
------------------------------------------------------------ ...

    cdef np.ndarray[np.double_t, ndim=2, mode="c"] X_c
    cdef np.ndarray[np.int_t, ndim=1, mode="c"] y_c
    X_c = np.ascontiguousarray(X, dtype=np.double)
    y_c = np.ascontiguousarray(y, dtype=np.int)
    retval = filedump( &X_c[0,0], numexemplars, numfeats, &y_c[0], outfnamestr)
                                                         ^
------------------------------------------------------------

fastdump_svm.pyx:24:58: Cannot assign type 'int_t *' to 'int *'

你知道如何修复这个错误吗?我最初遵循的是传递y_.c.数据的范例,这很有效,但这显然不是推荐的方式。

问题是
numpy.int_/code>与
int
不同,您可以通过让程序打印
sizeof(numpy.int_t)
sizeof(int)
来轻松检查这一点

int
是一个c int,由c标准定义为至少16位,但在我的机器上是32位
numpy.int\u t
通常是32位或64位,这取决于您使用的是32位还是64位版本的numpy,但当然也有一些例外(可能是windows用户)。如果您想知道哪个numpy数据类型与您的c_int匹配,可以执行
np.dtype(cytpes.c_int)

因此,要将numpy数组传递给c代码,可以执行以下操作:

import ctypes
cdef np.ndarray[int, ndim=1, mode="c"] y_c
y_c = np.ascontiguousarray(y, dtype=ctypes.c_int)
retval = filedump( &X_c[0,0], numexemplars, numfeats, &y_c[0], outfnamestr)

在启动numpy数组以匹配计算机上的C
int
时,也可以使用
dtype=np.dtype(“i”)

cdef int [:] y_c
c_array = np.ascontiguousarray(y, dtype=np.dtype("i"))

cdef中的数据类型应为int\u t,否?当我在没有int的情况下尝试时,我得到一个错误,即无法将指针强制转换到Python对象。当我使用int_t时,我得到了与以前相同的错误,关于从int_t*到int*的转换。对不起,我上次的评论,我似乎误解了你接下来的问题。cdef应具有与
filedump
的函数声明相同的类型,因此如果参数定义为
int target[]
,cdef应使用
int
。例如,如果您可以更改
filedump
的签名,您可以将它们都设置为
np.int\u t
,但它们应该相同。确保您使用的是
int
而不是
np.int
,第一个是c基本类型(至少在cdef块中使用时是这样),第二个是python类型。