2017-01-20 49 views
1

我有一個python memoryview指向一個bytes對象,我想在這個對象上執行一些cython處理。在字節對象上獲取指向python memoryview的指針

我的問題是:

  • 因爲bytes對象是不可寫,用Cython不允許從它構建一個類型化(用Cython)memoryview
  • 我不能使用指針,或者是因爲我不能讓一個指針所述memoryview開始

實施例:

在蟒蛇:

array = memoryview(b'abcdef')[3:] 

地用Cython:

  • cdef char * my_ptr = &array[0]失敗的消息編譯:Cannot take address of Python variable
  • cdef char[:] my_view = array失敗,在該消息的運行時:BufferError: memoryview: underlying buffer is not writable

怎樣才能解決這個問題?

+0

第一個問題:如何在你的Cython函數中聲明'array'參數? –

+0

@PierredeBuyl我把它作爲一個python對象傳入。像這樣:Cython:'def myfunc(arr):pass' – ARF

+0

嗨,經過一些文檔查找和谷歌搜索,如果你收到的所有內容都是內存視圖,看起來很難獲得讀寫訪問。你應該提到memoryview是如何在第一個地方創建的。如果你可以得到一個'Py_buffer'結構,這可能會有所幫助。 https://docs.python.org/3.5/c-api/buffer.html –

回答

1

您可以使用bytearray來創建可變內存視圖。請注意,這是不會改變的字符串,只有bytearray

data = bytearray('python') 
view = memoryview(data) 
view[0] = 'c' 
print data 
# cython 
+0

確實。這就是我現在正在做的事情。但是實例化一個臨時的'bytearray'對象會破壞使用cython加速我的算法的全部目的。 – ARF

0

使用bytearray(每@ CheeseLover的答案)可能是做事的正確方法。我的建議是完全在bytearrays工作,從而避免臨時轉換。但是:

char* can be directly created from a Python string(或bytes) - 見鏈接部分的結尾:

cdef char * my_ptr = array 
# you can then convert to a memoryview as normal in Cython 
cdef char[:] mview = <char[:len(array)]>my_ptr 

一對夫婦的警告:

  1. 記住bytes不可改變,如果你嘗試修改該內存視圖可能會導致問題
  2. my_ptr(因此mview)只有在array有效時纔有效,所以一定要參考保持到array,只要您需要訪問TI的數據,
+0

謝謝。我的問題是,我有一個'字節'對象。因此,我不能切換到'bytesarray'而不產生實例化的代價。 'char *'可以通過'bytes()'而不是'memoryview(bytes())'來創建。你的建議失敗,'TypeError:預期字節,發現內存視圖' – ARF

+0

對不起 - 我誤解了一些。你可以用'array.obj'(只有Python> = 3.3)從內存視圖中獲取'bytes'(不涉及複製),然後將其轉換爲'char *' – DavidW

+0

我也嘗試過:它丟失了內存視圖的偏移量。對於'test = memoryview(b'abcdef')[3:]''bytes(test)== b'def'' while test.obj == b'abcdef''。到目前爲止,我發現的唯一解決方案是我在下面的答案中的非常詳細的過程。 - 儘管我很想擺脫那種可怕的代碼混亂。 – ARF

2

好,通過Python API挖後,我發現了一個解決方案,使在一個指針bytes對象的緩衝區memoryview(這裏叫bytes_view = memoryview(bytes()))。也許這可以幫助別人:

from cpython.buffer cimport PyObject_GetBuffer, PyBuffer_Release, PyBUF_ANY_CONTIGUOUS, PyBUF_SIMPLE 


cdef Py_buffer buffer 
cdef char * my_ptr 

PyObject_GetBuffer(bytes, &buffer, PyBUF_SIMPLE | PyBUF_ANY_CONTIGUOUS) 
try: 
    my_ptr = <char *>buffer.buf 
    # use my_ptr 
finally: 
    PyBuffer_Release(&buffer) 
+1

正是我在找什麼..但什麼是你的代碼中的buffer_view?你的意思是「緩衝區」? –

+1

我剛試過這個,是的'buffer_view'應該是'buffer'。 –

+0

@ConradParker感謝您的注意。我複製了我的代碼中的代碼片段,並簡化了代碼片段,我弄亂了變量名稱以使其更清晰。我明顯錯過了......現在的代碼段是否適合你? – ARF