这是我的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]
答案 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
如果头文件使用宏定义函数,则将其声明为普通函数,并带有适当的参数和结果类型。