错误消息";无法转换<;键入_name>;*“到Python对象”;在赛昂
当我对以下Cython模块进行Cython化时错误消息";无法转换<;键入_name>;*“到Python对象”;在赛昂,python,cython,Python,Cython,当我对以下Cython模块进行Cython化时 %%cython cdef double *ptr=[1,2,3] print(ptr) 我收到以下错误消息: 无法将“double*”转换为Python对象 但是,以下Cython模块: %%cython cdef double val=0.0 print(val) 是没有问题的cythonized 任何其他指针类型(即int*,float*等)也会出现此问题 print是一个纯Python函数,为了能够调用它,参数必须是Python对象 显
%%cython
cdef double *ptr=[1,2,3]
print(ptr)
我收到以下错误消息:
无法将“double*”转换为Python对象
但是,以下Cython模块:
%%cython
cdef double val=0.0
print(val)
是没有问题的cythonized
任何其他指针类型(即
int*
,float*
等)也会出现此问题 print
是一个纯Python函数,为了能够调用它,参数必须是Python对象
显然,第一个Cython模块中的ptr
和第二个Cython模块中的val
都不是python对象。但是有一点不同:Cython可以通过自动将类型为double
的cdef
变量转换为Python浮点-这正是在后台发生的事情:Cython从val
创建一个临时Python浮点,将其传递给print
,然后将其销毁
还有其他类型可以自动转换为Python对象:double
、float
、int
&类似,但也有
但是,对于原始C指针(char*
,Py\u UNICODE*
,它们的不同转世是一个例外-请参见后面的示例)-没有这样的自动转换,因为首先是不可能的,因为Cython不知道数组的长度(它是数组吗?)指针指向的对象
这种情况下唯一的解决方案是:必须手动将内存内容转换为python列表(或它对应的任何python类型),例如函数convert\u to\u python
:
%%cython
cdef convert_to_python(double *ptr, int n):
cdef int i
lst=[]
for i in range(n):
lst.append(ptr[i])
return lst
cdef double *ptr=[1,2,3]
print(convert_to_python(ptr,3))
最值得注意的是,convert_to_python
获取作为参数的元素数-Cython缺少的信息
顺便说一句:Cython会自动将已知长度的C数组转换为Python对象,例如:
%%cython
cdef double arr[3] # length (=3) known to Cython
arr[:]=[1,2,3]
print(arr)
编译没有问题
char*
,signed char*
,unsigned char*
,Py_UNICODE*
及其const
变体是“特殊的”,因为它们可以连接到bytes
-对象(char*
)或UNICODE
-对象(Py UNICODE*
),假设它是以null结尾的C字符串(即字符\0
标记结束)。因此,可以编写类似
cdef char a[3]
a = [90,0,90] # ord('Z') = 90
print(a) # char[3] decays to char *
# b"Z"
可以看到,结果不是b“Z\x00Z”,因为字符串在第一个“\0”处会自动截断。要确保整个字符串转换为bytes对象,必须指定长度:
print(a[:3])
# b"Z\x00Z"
但是,如果char数组中没有\0
,则可能会出现问题,这可能会导致segfaults(读取超出范围)