2015-01-28 10 views
12

Wie kann ich eine Cython-Funktion schreiben, die ein Byte-String-Objekt (eine normale Zeichenfolge, ein Bytearray oder ein anderes Objekt, das dem buffer protocol folgt) als typed memoryview schreibt?Wie Cython typed memoryviews verwendet werden, um Zeichenfolgen von Python zu akzeptieren?

Nach dem Unicode and Passing Strings Cython Tutorial Seite sollten folgende Arbeiten:

cpdef object printbuf(unsigned char[:] buf): 
    chars = [chr(x) for x in buf] 
    print repr(''.join(chars)) 

Es funktioniert für Bytearrays und anderen beschreibbaren Puffer:

$ python -c 'import test; test.printbuf(bytearray("test\0ing"))' 
'test\x00ing' 

Aber es funktioniert nicht für normale Strings und andere schreibgeschützte Pufferobjekte:

$ python -c 'import test; test.printbuf("test\0ing")' 
Traceback (most recent call last): 
    File "<string>", line 1, in <module> 
    File "test.pyx", line 1, in test.printbuf (test.c:1417) 
    File "stringsource", line 614, in View.MemoryView.memoryview_cwrapper (test.c:6795) 
    File "stringsource", line 321, in View.MemoryView.memoryview.__cinit__ (test.c:3341) 
BufferError: Object is not writable. 

Looki ng am generierten C-Code übergibt Cython immer das PyBUF_WRITABLE-Flag an PyObject_GetBuffer(), die die Ausnahme erklärt.

Ich kann manuell einen Blick in die Puffer-Objekt selbst, aber es ist nicht so bequem:

from cpython.buffer cimport \ 
    PyBUF_SIMPLE, PyBUF_WRITABLE, \ 
    PyObject_CheckBuffer, PyObject_GetBuffer, PyBuffer_Release 

cpdef object printbuf(object buf): 
    if not PyObject_CheckBuffer(buf): 
     raise TypeError("argument must follow the buffer protocol") 
    cdef Py_buffer view 
    PyObject_GetBuffer(buf, &view, PyBUF_SIMPLE) 
    try: 
     chars = [chr((<unsigned char *>view.buf)[i]) 
       for i in range(view.len)] 
     print repr(''.join(chars)) 
    finally: 
     PyBuffer_Release(&view) 
$ python -c 'import test; test.printbuf(bytearray("test\0ing"))' 
'test\x00ing' 
$ python -c 'import test; test.printbuf("test\0ing")' 
'test\x00ing' 

Bin ich etwas falsch zu machen, oder hat Cython unterstützen Objekte nicht Nötigung schreibgeschützt Puffer (wie normale Strings) in typisierte memoryview-Objekte?

+0

Ich habe Ihren Patch [hier] gefunden (https://mail.python.org/pipermail/cython-devel/2015-February/004316.html), sogar das Hinzufügen von 'const' hilft nicht, also bedeutet das die vorgeschlagene Dokumentation funktioniert nicht. – dashesy

Antwort

18

Trotz der Dokumentation schlägt Cython (mindestens bis zur Version 0.22) nicht Unterstützung erzwingt Lese-Puffer-Objekte in typisierte MemoryView-Objekte. Cython übergibt immer das PyBUF_WRITABLE Flag an PyObject_GetBuffer(), auch wenn es keinen Schreibzugriff benötigt. Dies führt dazu, dass schreibgeschützte Pufferobjekte eine Ausnahme auslösen.

I raised this issue on the Cython developer mailing list, und sogar ein (sehr grober) Patch enthalten. Ich habe nie eine Antwort bekommen, also nehme ich an, dass die Cython-Entwickler nicht daran interessiert sind, diesen Fehler zu beheben.

+0

Ich habe das gleiche Problem, warum sind sie nicht daran interessiert, das zu beheben? – avocado

+0

Sie könnten versuchen, den Patch als eine GitHub-Pull-Anfrage zu senden; und Hinzufügen einiger Testfälle. – joeln

+0

Haben Sie tatsächlich versucht, den Patch durch GitHub zu schieben? –