[英]Error message "Cannot convert <type_name>* to Python object" in Cython
當我對以下 Cython 模塊進行 cythonize 時
%%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
和第二個模塊中的val
都不是 python 對象。 但是有一個區別:Cython 通過PyFloat_FromDouble
可以將double
類型的cdef
變量自動轉換為 Python-Float - 這正是幕后發生的事情:Cython 從val
創建一個臨時 Python-Float,將其傳遞給print
並在之后銷毀它。
還有其他類型可以自動轉換為 Python 對象: double
、 float
、 int
和類似的,還有std::vector
和其他 c++-containers 。
但是,對於原始 C 指針( 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))
最值得注意的是, 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
Py_UNICODE *
是“特殊的”,因為它們可以自動轉換為bytes
-object ( char *
) 或unicode
Py_UNICODE *
( Py_UNICODE *
),假設它是一個以空字符結尾的 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' 處被自動截斷。 為確保整個字符串轉換為字節對象,必須指定長度:
print(a[:3])
# b"Z\x00Z"
但是,如果字符數組中沒有\\0
,則會出現問題,這可能導致段錯誤(讀取越界)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.