Cython编译错误:说数组是结构

时间:2019-08-16 03:24:22

标签: cython cythonize

这是我的Cython错误的最低可复制版本。该代码在C ++中运行。

编译器告诉我错误C2088,“ + =对于结构是非法的”。但是,它正在传递一个数组。

pyx文件:

from libc.stdint cimport uint32_t as Card
from cpython cimport array
import array

cdef extern from "ace_eval.h":
    void ACE_addcard(h, Card c)

def create_hand():
    cdef array.array h = array.array('I',[0, 0, 0, 0, 0])
    ACE_addcard(h, 257)

    return h

从标头导入的函数是:

#define ACE_addcard(h,c)  h[c&7]+=c,h[3]|=c 

我也尝试使用以下方法声明我的数组 cdef Card h[5]

2 个答案:

答案 0 :(得分:1)

array.array是一个Python对象,最终将其编译为一个结构(因此C ++可以看到)。由__getitem____setitem__在Python级别控制对元素的访问,这些元素由Cython编译为C API函数调用。当Cython看到要操纵的数组的代码时,它将生成适当的C API函数调用。您使用C ++ #define语句进行编码会尝试在C ++编译时对其进行操作,并阻止Cython知道发生了什么。

理想情况下,您应该使用“类型化的内存视图”,以使Cython更快地访问数组(但是 still 不适用于C ++ #define,因为在Cython处理完文件):

cdef int[::1] h = array.array('I',[0, 0, 0, 0, 0]) # you may have to change the type long... I haven't tested it

h[257&7]+=257
h[3]|=257 

如果您绝对坚持使用宏,则它们需要使用C ++数组接口。指针可能是最简单的选项,可以从以下位置获取:

cdef int* h_ptr = &h[0]

答案 1 :(得分:0)

@DavidW的第二种方法

    cdef Card h[5]
    h[:] = [0, 0, 0, 0, 0]
    cdef Card* h_ptr = &h[0]

在我也调整了cdef以便接受指针后也起作用了。请注意,#define宏中的函数未更改,并且未指定返回类型。

cdef extern from "ace_eval.h":
       void ACE_addcard(Card* h, Card c)

这使我可以完美地传递我的任何数组。

这实际上是文档中所说的,但是对我来说有点钝-希望我的解释对其他人有所帮助。 https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html

  

如果头文件使用宏定义函数,则将其声明为普通函数,并带有适当的参数和结果类型。