如何使用Cython类型的memoryviews接受来自Python的字符串? [英] How to use Cython typed memoryviews to accept strings from Python?

查看:173
本文介绍了如何使用Cython类型的memoryviews接受来自Python的字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我该如何编写一个Cython函数,该函数接受一个字节字符串对象(普通字符串,字节数组或跟随输入的内存视图?

How can I write a Cython function that takes a byte string object (a normal string, a bytearray, or another object that follows the buffer protocol) as a typed memoryview?

根据 Unicode和传递字符串 Cython教程页面上,以下内容应该起作用:

According to the Unicode and Passing Strings Cython tutorial page, the following should work:

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

它确实适用于字节数组和其他可写缓冲区:

It does work for bytearrays and other writable buffers:

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

但是它不适用于普通字符串和其他只读缓冲区对象:

But it doesn't work for normal strings and other read-only buffer objects:

$ 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.

查看生成的C代码,Cython始终将PyBUF_WRITABLE标志传递给PyObject_GetBuffer(),这说明了异常.

Looking at the generated C code, Cython is always passing the PyBUF_WRITABLE flag to PyObject_GetBuffer(), which explains the exception.

我可以自己手动查看缓冲区对象的视图,但这并不方便:

I can manually get a view into the buffer object myself, but it's not as convenient:

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'

我做错什么了吗,还是Cython不支持将只读缓冲区对象(例如普通字符串)强制转换为类型化的memoryview对象?

Am I doing something wrong, or does Cython not support coercing read-only buffer objects (such as normal strings) into typed memoryview objects?

推荐答案

尽管文档中另有说明,但是Cython(至少在0.22版之前)不支持将只读缓冲区对象强制转换为类型memoryview对象. Cython始终将PyBUF_WRITABLE标志传递给 PyObject_GetBuffer(),即使它不需要写访问权限.这将导致只读缓冲区对象引发异常.

Despite the documentation suggesting otherwise, Cython (at least up to version 0.22) does not support coercing read-only buffer objects into typed memoryview objects. Cython always passes the PyBUF_WRITABLE flag to PyObject_GetBuffer(), even when it doesn't need write access. This causes read-only buffer objects to raise an exception.

在Cython开发者邮件列表中提出了这个问题,甚至包括一个(非常粗糙的)补丁.我没有得到任何回复,所以我认为Cython开发人员对修复此错误没有兴趣.

I raised this issue on the Cython developer mailing list, and even included a (very rough) patch. I never got a reply, so I assume the Cython developers are not interested in fixing this bug.

这篇关于如何使用Cython类型的memoryviews接受来自Python的字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆