Cython:无法将Python对象转换为'double *'

时间:2013-06-09 21:30:34

标签: python arrays list cython

我正在为C函数编写一个Cython包装器。我有一个带有以下签名的pxd文件:

double contr_hrr(int lena, double xa, double ya, double za, double *anorms)

当我尝试从pyx文件中调用它时

...
return contr_hrr(len(acoefs),a.origin[0],a.origin[1],a.origin[2],anorms2)

其中 anorms2 是一个python列表,我收到错误消息:

cython/ctwo.pyx:35:80: Cannot convert Python object to 'double *'

如何将python列表作为双数组传递给C函数?

3 个答案:

答案 0 :(得分:8)

  1. cimport array

    from cpython cimport array
    
  2. 从列表中创建一个数组对象。数组类构造函数将执行所有繁重的重组分配内存并迭代您的列表(实际上可以是任何迭代)。

    cdef array.array anorms2_arr = array.array('d', anorms2)
    
  3. 将其数据传递给您的函数:

    return contr_hrr(.., anorms2_arr.data.as_doubles)
    
  4. arraystandard Python module。 Cython在顶部添加了一些特殊支持,如缓冲区接口和通过arr.data.as_xxx直接访问底层内存块。不幸的是,此支持仅记录here。 您还可以在this recent thread中找到有关数组使用情况的一些详细信息。

答案 1 :(得分:4)

我认为你不能这样做,而是自己转换它:

cimport cython
from libc.stdlib cimport malloc, free

...
cdef double *anorms
cdef unsigned int i;

anorms = <double *>malloc(len(anorms2)*cython.sizeof(double))
if anorms is NULL:
    raise MemoryError()

for i in xrange(len(anorms2)):
    anorms[i] = anorms2[i]

return contr_hrr(len(acoefs),a.origin[0],a.origin[1],a.origin[2],anorms)

如果你曾经使用过C ++,那就不一样了,因为

The following coercions are available:
Python type   =>   C++ type             => Python type
bytes              std::string             bytes
iterable           std::vector             list
iterable           std::list               list
iterable           std::set                set
iterable (len 2)   std::pair               tuple (len 2)

如果您可以切换到C ++,则可以直接从List[float]转换为vector<double>

from libcpp.vector cimport vector

def py_contr_hrr(vector[double] anorms2, ...):
    ...
    return contr_hrr(len(acoefs),a.origin[0],a.origin[1],a.origin[2],anorms2)

直接从Python方面调用:

anorms2 = [12.0, 0.5, ...]
py_contr_hrr(anorms2, ....)

来源:http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#standard-library

但我不知道你是否可以考虑这个选项......当然,这取决于你项目的限制。

编辑:我不知道Nikita的做法(顺便说一下,这是一个优雅的做法),我不知道以哪种方式最适合大表演阵列。

答案 2 :(得分:2)

我最终做的是确保将anorms数组维护为代码的python部分中的数组,然后使用Nikita的配方将它们动态转换为使用.data.as_doubles属性的双精度数。如果我这样做,与在C中本地执行任何操作相比,它似乎只有很少的开销。

由于各种普通的原因,尚未尝试采用numpy方法。