全部。下面有一个Cython代码示例,其中有一个无符号字符数组,a
填充了无符号整数。当我将这个数组传入Pythondef
方法时,包含0的索引之后的任何索引的值都会变得混乱。你知道吗
在本例中,由于0的值位于第6个索引处,因此从数组传递到__cinit__()
方法的所有后续数组索引的值都不正确。这种行为也发生在__init__()
方法或任何使用Python声明的函数或方法def
。你知道吗
但是,当数组被传递到任何cdef
或cpdef
函数或方法时,数组的值是正确的。你知道吗
因此,我有两个问题(请注意,我使用的是.pyx runner文件):
__cinit__()
方法中?还有别的办法吗?你知道吗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函数的所有参数都是Python对象。
char *
(与unsigned char *
相同)不是Python对象,但是可以将(某些)Python对象自动转换为char *
。所以呢Cython的方法:检查传递的Python对象是否可以转换为
cdef char *
,执行转换并在函数体中使用此转换的结果。你知道吗调用带有
char *
(另请参见此有点相关的SO-post)作为参数的def函数时:Cython执行以下操作:使用
char *
的自动转换,假设它是一个以null结尾的c字符串到bytes对象,并将这个临时bytes对象传递给def
-函数bar
。你知道吗这意味着在你的情况下:
foo(a)
创建一个长度为5(而不是12,因为第6个元素是0
)的临时bytes对象,前5个字符被复制到该对象。你知道吗foo
中,这个bytes对象的缓冲区的地址作为unsigned char *b
使用,它现在只有6个元素(包括后面的\0
),因此通过b[6]
访问它是未定义的行为,可能会导致分段错误。你知道吗您可以通过验证
a
和b
指向不同的地址所以问题实际上是,当调用
foo
时,并不是整个数组都转换成临时的bytes
对象。从/到char *
的转换在Cython-documentation中描述。在您的情况下,电话应该是:现在打印以下内容:
这种情况对于
cdef
-函数是不同的,其中char *
保持char *
,并且不转换为Python对象。但是,__cinit__
必须是def
函数,因此在这种情况下通常使用cdef
-工厂函数,如the answer pointed out by @DavidW,例如:显然,
Classical.create
只能从Cython代码中使用,但另一方面,只有Cython代码才有指针!你知道吗相关问题 更多 >
编程相关推荐