print
是一个纯Python函数,为了能够调用它,参数必须是Python对象。
ptr
在第一个Cython模块中,nor
val
第二种是python对象。但是有一个区别:a
cdef
double
可以通过Cython自动转换为Python浮点
PyFloat_FromDouble
-这正是幕后发生的事情:Cython从
瓦尔
打印
然后把它毁掉。
还有其他类型可以自动转换为Python对象:
,
float
int
&相似,但也
std::vector
and other c++-containers
.
char *
,
Py_UNICODE*
它们的不同转世是一个例外(见后面的示例),因为这首先是不可能的,因为Cython不知道指针指向的数组(到底是数组吗?)的长度。
这种情况下唯一的解决方案是:必须手动将内存内容转换为python列表(或它对应的任何python类型),这里以函数为例
convert_to_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))
最值得注意的是,
获取作为参数的元素数-缺少信息Cython。
顺便说一句:Cython会自动将已知长度的C数组转换为Python对象,例如:
%%cython
cdef double arr[3] # length (=3) known to Cython
arr[:]=[1,2,3]
print(arr)
煤焦*
signed char *
,
unsigned char *
Py_UNICODE *
以及他们的
const
-变体是“特殊的”,因为它们可以
be automatically converted
要么
bytes
煤焦*
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"
但是,如果没有,问题可能会出现
\0
在char数组中,这可能导致segfaults(读取超出范围)。