直接写入位字段的缓冲区

时间:2018-06-28 15:17:41

标签: python buffer bit-fields

我正在研究Python中ctypes的位字段结构,我有一个问题。 是否可以直接写入下面定义的Packet Union的缓冲区?

from ctypes import c_uint8

class PacketBits(ctypes.LittleEndianStructure):
  _fields_ = [
      # First byte
      ("a", ctypes.c_uint8, 4),
      ("b", ctypes.c_uint8, 3),
      ("c", ctypes.c_uint8, 1),
      # Second byte
      ("d", ctypes.c_uint8, 5),
      ("e", ctypes.c_uint8, 3),
      # Third byte
      ("f", ctypes.c_uint8, 4),
      ("g", ctypes.c_uint8, 4),
      # Fourth byte
      ("h", ctypes.c_uint8, 2),
      ("i", ctypes.c_uint8, 6),
      # Fifth byte
      ("j", ctypes.c_uint8, 4),
      ("k", ctypes.c_uint8, 3),
      ("l", ctypes.c_uint8, 1),
      # Sixth byte
      ("m", ctypes.c_uint8, 5),
      ("n", ctypes.c_uint8, 3),
      # Seventh byte
      ("o", ctypes.c_uint8, 4),
      ("p", ctypes.c_uint8, 4),
      # Eighth byte
      ("q", ctypes.c_uint8, 2),
      ("r", ctypes.c_uint8, 6),
  ]

class Packet(ctypes.Union):
    _fields_ = [("bits", PacketBits),
                ("binary_data", 8 * c_uint8)]

我问这个问题是因为我需要解析一个65字节的流,并在其中定义一些位。

我尝试使用位数组直接设置它,...而我尝试的所有方法都不成功。

有人知道吗?

最诚挚的问候。

Johan

1 个答案:

答案 0 :(得分:0)

我找到了一个解决方案,我在Packet类中使用了setter和getter:

class Packet(ctypes.Union):
    _fields_ = [("bits", PacketBits),
                ("binary_data", 8 * ctypes.c_uint8)]

    def get_binary_data(self):
        data = []
        for byte in self.binary_data:
            data.append(byte) 

        return data

    def set_binary_data(self, data = b'\x0D\x0E\x0A\x0D\x0B\x0E\x0E\x0F'):
        if len(data) <= len(self.binary_data):
            for index in range(len(data)):
                self.binary_data[index] = data[index]

但是现在实例化Packet类时,我可以访问binary_data,setter和getter。

然后有两个访问binary_data的权限。

我想允许一个访问(通过setter和getter访问),然后尝试使用这样的属性:

class Packet(ctypes.Union):
    _fields_ = [("bits", PacketBits),
                ("binary_data", 8 * ctypes.c_uint8)]

    @property
    def binary_data(self):
        data = []
        for byte in self.binary_data:
            data.append(byte) 

        return data

    @binary_data.setter
    def binary_data(self, data = b'\x0D\x0E\x0A\x0D\x0B\x0E\x0E\x0F'):
        if len(data) <= len(self.binary_data):
            for index in range(len(data)):
                self.binary_data[index] = data[index]

In [2]: p = Packet()

In [3]: p.binary_data()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-5caaf0aaa9ce> in <module>()
----> 1 p.binary_data()

TypeError: 'c_ubyte_Array_8' object is not callable

In [4]: p.binary_data
Out[4]: <test.c_ubyte_Array_8 at 0x7f7d538bf400>

In [5]: p.binary_data = b'\xaa'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-6a26479e789c> in <module>()
----> 1 p.binary_data = b'\xaa'

TypeError: expected c_ubyte_Array_8 instance, got bytes

任何人都知道如何正确使用属性和设置器?

Johan