错误消息";无法转换<;键入_name>;*“到Python对象”;在赛昂

错误消息";无法转换<;键入_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模块进行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模块中的
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(读取超出范围)