2015-01-28 33 views
12

Come posso scrivere una funzione Cython che accetta un oggetto stringa di byte (una stringa normale, un bytearray o un altro oggetto che segue lo buffer protocol) come typed memoryview?Come utilizzare le visioni di memoria tipizzate da Cython per accettare stringhe da Python?

Secondo la pagina di esercitazione Unicode and Passing Strings Cython, il seguente dovrebbe funzionare:

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

funziona per bytearrays e altri buffer scrivibili:

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

Ma non funziona per le stringhe normali e altri oggetti buffer di sola lettura:

$ 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 al codice C generato, Cython passa sempre il flag PyBUF_WRITABLE a PyObject_GetBuffer(), che spiega l'eccezione.

posso ottenere manualmente una vista nel buffer obiettare me stesso, ma non è così conveniente:

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' 

sto facendo qualcosa di sbagliato, o non Cython non supportare costringere sola lettura tampone oggetti (come le normali stringhe) in oggetti memoryview digitati?

+0

Ho trovato la tua patch [qui] (https://mail.python.org/pipermail/cython-devel/2015-February/004316.html) aggiungendo anche 'const' non aiuta, quindi questo significa la documentazione suggerita non funziona. – dashesy

risposta

18

Nonostante la documentazione suggerisca il contrario, Cython (almeno fino alla versione 0.22) fa non supporto coercing di oggetti buffer di sola lettura in oggetti memoryview digitati. Cython passa sempre il flag PyBUF_WRITABLE a PyObject_GetBuffer(), anche quando non è necessario l'accesso in scrittura. Ciò fa sì che gli oggetti buffer di sola lettura generino un'eccezione.

I raised this issue on the Cython developer mailing list e persino incluso una patch (molto approssimativa). Non ho mai avuto una risposta, quindi presumo che gli sviluppatori Cython non siano interessati a risolvere questo bug.

+0

Anche io ho lo stesso problema, perché non sono interessati a risolvere questo problema? – avocado

+0

Si potrebbe provare a inviare la patch come richiesta pull GitHub; e aggiungendo in alcuni casi di test. – joeln

+0

In effetti, hai provato a trasmettere la patch tramite GitHub? –