Cython で Python 2.7 拡張モジュールを作成しています。 C ライブラリから提供されたメモリのチャンクをラップする新しいスタイルのバッファ インターフェイスを実装する Python オブジェクトを作成するにはどうすればよいですか? メモリのチャンクは単なるバイト文字列であり、構造体や多次元配列ではありません。ポインターと長さ、およびポインターの有効期間に関する詳細が与えられconst void *
ます。
メモリをコピーできません。アプリケーションのパフォーマンスが低下します。
古いスタイルのバッファ オブジェクトでは単純に を使用できPyBuffer_FromMemory()
ましたが、新しいスタイルのバッファ オブジェクトを生成する同様に簡単な方法が見つからないようです。
バッファ インターフェイスを実装する独自のクラスを作成する必要がありますか? または、Cython はこれを行う簡単な方法を提供していますか?
Cython のドキュメントからUnicode と Passing StringsとTyped Memoryviewsのページを読みましたが、ドキュメントは不正確で完全ではなく、私がやりたいことに似た例はありません。
これが私が試したことです(test.pyx
):
from libc.stdlib cimport malloc
from libc.string cimport memcpy
## pretend that this function is in some C library and that it does
## something interesting. (this function is unrelated to the problem
## I'm experiencing -- this is just an example function that returns a
## chunk of memory that I want to wrap in an object that follows the
## new buffer protocol.)
cdef void dummy_function(const void **p, size_t *l):
cdef void *tmp = malloc(17)
memcpy(tmp, "some test\0 bytes", 17)
p[0] = tmp
l[0] = 17
cpdef getbuf():
cdef const void *cstr
cdef size_t l
dummy_function(&cstr, &l)
## error: test.pyx:21:20: Invalid base type for memoryview slice: void
#cdef const void[:] ret = cstr[:l]
## error: test.pyx:24:9: Assignment to const 'ret'
#cdef const char[:] ret = cstr[:l]
## error: test.pyx:27:27: Cannot convert 'void const *' to memoryviewslice
#cdef char[:] ret = cstr[:l]
## this next attempt cythonizes, but raises an exception:
## $ python -c 'import test; test.getbuf()'
## Traceback (most recent call last):
## File "<string>", line 1, in <module>
## File "test.pyx", line 15, in test.getbuf (test.c:1411)
## File "test.pyx", line 38, in test.getbuf (test.c:1350)
## File "stringsource", line 614, in View.MemoryView.memoryview_cwrapper (test.c:6763)
## File "stringsource", line 321, in View.MemoryView.memoryview.__cinit__ (test.c:3309)
## BufferError: Object is not writable.
cdef char[:] ret = (<const char *>cstr)[:l]
## this raises the same exception as above
#cdef char[:] ret = (<char *>cstr)[:l]
return ret