加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

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'

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读