Битовые значения полей структуры

Есть структура, объявление на С которой выглядит так:

   struct Strip {
      ULONG InJob: 1
      ULONG Initializing : 1
      ULONG UsingPool : 1
      ULONG UsingPages : 1
      ULONG FormFactor : 1
      ULONG Reserved: 27
   }

Как подобные структуры объявляются в Python? Как объявляются обычные структуры, без побитового значения полей, я знаю, например:

class Foo(Structure):
   _fields_ = [('a', c_ulong), ('b', c_long)]

А вот как с битовыми значениями - не имею понятия.


Ответы (1 шт):

Автор решения: Teivaz

У ctypes.Structure есть битовые поля.

Для структуры

struct Strip {
    unsigned long InJob: 1;
    unsigned long Initializing : 1;
    unsigned long UsingPool : 1;
    unsigned long UsingPages : 1;
    unsigned long FormFactor : 1;
    unsigned long Reserved: 27;
}

эквивалентом будет

class Strip(ctypes.Structure):
    _fields_ = [
        ("InJob", ctypes.c_ulong, 1),
        ("Initializing", ctypes.c_ulong, 1),
        ("UsingPool", ctypes.c_ulong, 1),
        ("UsingPages", ctypes.c_ulong, 1),
        ("FormFactor", ctypes.c_ulong, 1),
        ("Reserved", ctypes.c_ulong, 27),
    ]

Вот только битовые поля очень нестабильно работают в python: они не кросс-платформенные.

Существует встроенный модуль struct, он очень прост и функционален. Но, к сожалению, не умеет работать с отдельными битам, а только лишь с октетами.

Как альтернативу я использовал простые битовые маски:

class Strip:
    def __init__(self, inputStream):
        raw = struct.unpack("L", inputStream.read(4))
        self.InJob =        (raw & 0b0000000000000001) >> 0
        self.Initializing = (raw & 0b0000000000000010) >> 1
        self.UsingPool =    (raw & 0b0000000000000100) >> 2
        self.UsingPages =   (raw & 0b0000000000001000) >> 3
        self.FormFactor =   (raw & 0b0000000000010000) >> 4
        self.Reserved =     (raw & 0b1111111111100000) >> 5

Вот тут можно посмотреть как я использовал этот подход.

P.S. только будьте осторожны с порядком байтов.

→ Ссылка