मैं साइथन में एक पायथन 2.7 एक्सटेंशन मॉड्यूल लिख रहा हूं। मैं एक लाइब्रेरी ऑब्जेक्ट कैसे बना सकता हूं जो नए स्टाइल बफर इंटरफेस को कार्यान्वित करता है जो सी लाइब्रेरी द्वारा मुझे दी गई मेमोरी का एक हिस्सा लपेटता है? स्मृति का हिस्सा केवल बाइट्स की एक स्ट्रिंग है, न कि संरचना या बहुआयामी सरणी। मुझे const void *
पॉइंटर और लम्बाई दी गई है, और कुछ विवरण यह है कि पॉइंटर कब तक वैध रहता है।साइथन में एक नई शैली बफर ऑब्जेक्ट में सी पॉइंटर और लंबाई को कैसे लपेटें?
मैं स्मृति की प्रतिलिपि नहीं बना सकता-जो मेरे आवेदन के लिए प्रदर्शन को मार देगा।
पुराने स्टाइल बफर ऑब्जेक्ट्स के साथ मैं बस PyBuffer_FromMemory()
का उपयोग कर सकता हूं, लेकिन मुझे एक नई शैली बफर ऑब्जेक्ट बनाने के लिए एक आसान तरीका नहीं मिल रहा है।
क्या मुझे अपनी खुद की कक्षा बनाना है जो बफर इंटरफेस लागू करता है? या साइथन इसे करने का एक आसान तरीका प्रदान करता है?
मैंने साइथन दस्तावेज से Unicode and 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
शायद यह असफल रहा है क्योंकि आप 'char *' के बजाय 'const char *' पर कास्टिंग कर रहे हैं? – Kevin
@ केविन: मैंने अपने प्रश्न को यह बताने के लिए अद्यतन किया कि एक ही अपवाद तब भी होता है जब मैं 'const *' के बजाय 'char *' पर जाता हूं। यह बात बताने के लिए धन्यवाद। –
अधिक विस्तार से समस्या का अध्ययन करने के बाद, मैं यह इंगित करना चाहता हूं कि memcpy अवैध है। आपने 'tmp' को कॉन्स के रूप में घोषित किया है, और फिर आपने इसे संशोधित किया है। यह सी मानक द्वारा अपरिभाषित व्यवहार है। चूंकि आपने यह भी कहा है कि आप स्मृति की प्रतिलिपि से बचने की कोशिश कर रहे हैं, मैं इस बिंदु पर थोड़ा उलझन में हूं। – Kevin