python-2.7 – Ctypes from_buffer,包含Python 2.7和Python 3.4
发布时间:2020-12-20 11:41:27 所属栏目:Python 来源:网络整理
导读:我试图将数据从memoryview传递到ctypes数组,这在 Python 3.4中运行良好,但在Python 2.7中运行不正常. 我跑的时候 from ctypes import c_bytedata = memoryview(b'012')array = c_byte * 3array.from_buffer_copy(data) 我得到 __ main __.c_byte_Array_3 at
我试图将数据从memoryview传递到ctypes数组,这在
Python 3.4中运行良好,但在Python 2.7中运行不正常.
我跑的时候 from ctypes import c_byte data = memoryview(b'012') array = c_byte * 3 array.from_buffer_copy(data) 我得到< __ main __.c_byte_Array_3 at 0x7f3022cb8730>在Python 3.4中,但在Python 2.7.6中我收到以下错误: Traceback (most recent call last): File "<stdin>",line 1,in <module> TypeError: expected a readable buffer object 这个错误的原因是什么,以及我如何在这两种情况下都能完成这项工作? 我知道我可以使用将数据转换为字节 array.from_buffer_copy(data.tobytes()) 但我认为这是一个额外的数据副本,并不优雅,所以我正在寻找一个更好的解决方案(任何关于tobytes方法是否有效的评论也是受欢迎的). 解决方法
这是一个允许您使用Python 2 memoryview对象导出的缓冲区接口创建ctypes数组的类.
from ctypes import * pyapi = PyDLL("PythonAPI",handle=pythonapi._handle) PyBUF_SIMPLE = 0 PyBUF_WRITABLE = 0x0001 PyBUF_FORMAT = 0x0004 PyBUF_ND = 0x0008 PyBUF_STRIDES = 0x0010 | PyBUF_ND PyBUF_C_CONTIGUOUS = 0x0020 | PyBUF_STRIDES PyBUF_F_CONTIGUOUS = 0x0040 | PyBUF_STRIDES PyBUF_ANY_CONTIGUOUS = 0x0080 | PyBUF_STRIDES PyBUF_INDIRECT = 0x0100 | PyBUF_STRIDES PyBUF_CONTIG_RO = PyBUF_ND PyBUF_CONTIG = PyBUF_ND | PyBUF_WRITABLE PyBUF_STRIDED_RO = PyBUF_STRIDES PyBUF_STRIDED = PyBUF_STRIDES | PyBUF_WRITABLE PyBUF_RECORDS_RO = PyBUF_STRIDES | PyBUF_FORMAT PyBUF_RECORDS = PyBUF_STRIDES | PyBUF_FORMAT | PyBUF_WRITABLE PyBUF_FULL_RO = PyBUF_INDIRECT | PyBUF_FORMAT PyBUF_FULL = PyBUF_INDIRECT | PyBUF_FORMAT | PyBUF_WRITABLE Py_ssize_t = c_ssize_t Py_ssize_t_p = POINTER(Py_ssize_t) class pybuffer(Structure): """Python 3 Buffer Interface""" _fields_ = (('buf',c_void_p),('obj',# owned reference ('len',Py_ssize_t),# itemsize is Py_ssize_t so it can be pointed to # by strides in the simple case. ('itemsize',('readonly',c_int),('ndim',('format',c_char_p),('shape',Py_ssize_t_p),('strides',('suboffsets',# static store for shape and strides of # mono-dimensional buffers. ('smalltable',Py_ssize_t * 2),('internal',c_void_p)) def get_buffer(self,obj=None,flags=PyBUF_SIMPLE): self.release_buffer() Structure.__init__(self) if obj is not None: pyapi.PyObject_GetBuffer(obj,byref(self),flags) def make_release_buffer(): import ctypes PyBuffer_Release = pyapi.PyBuffer_Release memset = ctypes.memset byref = ctypes.byref sizeof = ctypes.sizeof def release_buffer(self): if self.obj: PyBuffer_Release(byref(self)) memset(byref(self),sizeof(self)) return release_buffer __init__ = get_buffer __del__ = release_buffer = make_release_buffer() del make_release_buffer @property def as_ctypes(self): if self.obj and self.buf: arr = (c_char * self.len).from_address(self.buf) if self.readonly: arr = type(arr).from_buffer_copy(arr) else: obj = py_object.from_buffer(c_void_p(self.obj)).value arr._obj = obj return arr pyapi.PyObject_GetBuffer.argtypes = (py_object,# obj POINTER(pybuffer),# view c_int) # flags pyapi.PyBuffer_Release.argtypes = POINTER(pybuffer),# view __all__ = [n for n in list(globals()) if n.startswith('PyBUF')] __all__.append('pybuffer') 例子: >>> data = memoryview(b'012') >>> buf = pybuffer(data) >>> buf.readonly 1 >>> array = buf.as_ctypes >>> array[0] = '9' >>> data[0] '0' >>> data = memoryview(bytearray(b'012')) >>> buf = pybuffer(data) >>> buf.readonly 0 >>> array = buf.as_ctypes >>> array[0] = '9' >>> data[0] '9' (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |