all.我在下面有一个 Cython 代码示例,其中我有一个无符号的 char 数组,a
填充了无符号整数。当我将此数组传递到 Pythondef
方法中时,包含 0 的索引之后的任何索引的值都会变得混乱。
在此示例中,由于值 0 位于第 6 个索引处,因此传入__cinit__()
方法的数组中的所有后续数组索引都具有不正确的值。对于__init__()
方法或使用 Python 声明def
的任何函数或方法,也会发生此行为。
但是,当数组传递到任何cdef
或cpdef
函数或方法时,数组的值是正确的。
所以,我有两个问题(请注意,我使用的是 .pyx runner 文件(:
- 我是否正确地将数组传递到
__cinit__()
方法中?有没有其他方法可以做到这一点? - 或者,是否有一种 Cythonic 方法来替换
def __cinit__()
方法?当然,我可以使用解决方法并使用cdef
或cpdef
方法,特别是对于我正在展示的这个简单的小示例,但我想了解是否有不同的方法......
法典:
cdef class Classical:
def __cinit__(self, unsigned char *b):
for x in range(0, 12):
print b[x], " init" # This does not work
cdef void bar(self, unsigned char *b):
for x in range(0, 12):
print b[x], " method" # This works fine
def foo(unsigned char *b):
for x in range(0, 12):
print b[x], " function" # This does not work either
cdef unsigned char a[12]
a = [
83,
12,
85,
31,
7,
0,
91,
11,
0,
12,
77,
100
]
Classical(a).bar(a)
foo(a)
输出:
83 init
12 init
85 init
31 init
7 init
0 init
0 init
0 init
0 init
0 init
0 init
0 init
83 method
12 method
85 method
31 method
7 method
0 method
91 method
11 method
0 method
12 method
77 method
100 method
83 function
12 function
85 function
31 function
7 function
0 function
100 function
0 function
0 function
0 function
0 function
0 function
def-function 的所有参数都是 Python 对象。char *
(unsigned char *
相同(不是 Python 对象,但是可以自动将(某些(Python 对象转换为char *
。所以
def foo(char *x):
...
Cython的意思是:检查传递的Python对象是否可以转换为cdef char *
,执行转换并在函数体中使用此转换的结果。
当调用带有char *
的 def-函数时(另请参阅这个有点相关的 SO-post(作为参数:
cdef char a[12]
....
bar(a) # a decays to char *
Cython 执行以下操作:假设char *
是一个以 null 结尾的 c 字符串,则使用自动转换到字节对象,并将此临时字节对象传递给def
函数bar
。
这意味着在您的情况下:
- 调用
foo(a)
会创建一个长度为 5 的临时字节对象(而不是 12,因为第 6 个元素是0
(,前 5 个字符被复制到该对象中。 - 在函数
foo
内部,这个字节对象的缓冲区的地址被获取并用作unsigned char *b
,现在只有6个元素(包括尾随