2017-01-20 72 views
1

私はbytesオブジェクトを指しているpython memoryviewを持っています。このオブジェクトでは、私はcythonで何らかの処理をしたいと思っています。バイトオブジェクトのPython memoryviewへのポインタの取得

私の問題は、次のとおりです。

  • bytesオブジェクトが書き込み可能ではないので、cythonは
  • それから型付き(cython)memoryviewを構築することはできません私はへのポインタを取得することはできませんので、私はどちらかのポインタを使用することはできませんで

    :memoryviewは

例を開始しますパイソン:cythonで

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

  • 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

最初の質問:あなたはどのようにあなたの中で '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を使用すると、変更可能なメモリビューを作成できます。のみ(CheeseLoverの答え@あたりとして)bytearrayを使用してbytearray

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

確かに。それは私が今やっていることです。しかし、一時的なbytearrayオブジェクトをインスタンス化することは、アルゴリズムを高速化するためにcythonを使うという全目的に反するものです。 – ARF

0

はおそらく物事の正しい方法で、これは文字列を変更しないことに注意してください。私の助言は完全に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が有効である限り有効ですので、限り、あなたはアクセスtiのデータを必要とするためにarrayへの参照を保持するようにしてください
+0

ありがとうございます。私の問題は、 'bytes'オブジェクトが与えられていることです。したがって、インスタンス化のコストを犠牲にすることなく 'bytesarray'に切り替えることはできません。 'char *'は 'bytes()'から作成できますが、 'memoryview(bytes())'では作成できません。あなたの提案は 'TypeError:expected bytes、memoryview found'で失敗します。 – ARF

+0

ああ、申し訳ありません - 私は少し誤解しました。 'array.obj'を使ってmemoryviewから' bytes'を返すことができます(Python> = 3.3だけです)。それを 'char *'にキャストします。 – DavidW

+0

私もそれを試しました。メモリビューのオフセット。 test.obj == b'abcdef''の間に 'test = memoryview(b'abcdef ')[3:]' 'bytes(test)== b'def''です。私が今までに見つけた唯一の解決策は、私の答えでは非常に冗長な手順です。 - 私は恐ろしいコードクラッタを取り除きたいですが。 – ARF

2

[OK]を、私は中bytesオブジェクトのバッファへのポインタを取得するために解決策を見つけたPythonのAPIを介して掘った後、メモリビュー(ここでは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ノートをありがとう。コードからスニペットをコピーしました。単純化すると、変数名がわかりやすくなりました。私は明らかに1つを逃した...今のようにコードスニペットはあなたのために働いていますか? – ARF

関連する問題