簡體   English   中英

錯誤消息“無法轉換<type_name> * 到 Python 對象”在 Cython 中

[英]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 對象: doublefloatint和類似的,還有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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM