Cython compiling error: Saying that Array is a Struct

Cython compiling error: Saying that Array is a Struct

这是我的 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

从header导入的函数是:

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

我也尝试过使用声明我的数组 cdef Card h[5]

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

理想情况下,您应该使用 "typed memoryviews" 来让 Cython 更快地访问数组(但是 仍然 不能与 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]

@DavidW的第二种方式

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

我也像这样调整了我的 cdef 以接受指针后,它也起作用了。请注意,#define 宏中的函数未更改且未指定 return 类型。

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

If the header file defines a function using a macro, declare it as though it were an ordinary function, with appropriate argument and result types.