I have created a ctype bitfield structure with a corresponding Union to access it both by single bitfield and by integer value. I was able to set the single field using a variable that contains the name of the field, but now I'd like to know to which byte the specific field belongs to. Here is an example of my code:
import ctypes
c_short = ctypes.c_uint16
class Flags_bits(ctypes.LittleEndianStructure):
_fields_ = [
("bitField1", c_short, 1),
("bitField2", c_short, 4),
("bitField3", c_short, 6),
("bitField4", c_short, 1),
("bitField5", c_short, 2),
("bitField6", c_short, 2),
("bitField7", c_short, 6),
("bitField8", c_short, 4),
("bitField9", c_short, 4),
("bitField10", c_short, 1),
("bitField11", c_short, 1)]
class Flags(ctypes.Union):
_fields_ = [("b", Flags_bits),
("asInt", c_short*6)]
def setFlag (flagName, value):
flags = Flags()
setattr(flags.b, flagName, value)
print getattr(flags.b, flagName)
Now what I want to know is to which integer my flag belongs to (i.e. to which flags.asInt[i]), I was looking for a sort of "get_location" attribute to get the flag location in the structure and from this retrieve the 'i' index of the integer, but I couldn't find anything Is there a simple way to do that?
Thanks in advance for every reply!
Each field descriptor in a Structure
has an offset
attribute that defines the byte offset of its storage unit. It also has a size
attribute whose meaning depends on whether or not it's a bit field. If it's a bit field, the low word of size
contains the field's storage-unit bit offset, and the high word contains the number of bits in the field. Otherwise size
is the field's size in bytes.
Since your bit-field storage units are all c_short
, you can simply divide a field's byte offset
by sizeof(c_short)
to calculate the corresponding item in asInt
. For example, Flags_bits.bitField6.offset // 2 == 0
and Flags_bits.bitField7.offset // 2 == 1
.
You can also compute the range of bits for each field:
import ctypes
c_short = ctypes.c_cshort
class Flags_bits(ctypes.LittleEndianStructure):
_fields_ = [("bitField1", c_short, 1),
("bitField2", c_short, 4),
("bitField3", c_short, 6),
("bitField4", c_short, 1),
("bitField5", c_short, 2),
("bitField6", c_short, 2),
("bitField7", c_short, 6),
("bitField8", c_short, 4),
("bitField9", c_short, 4),
("bitField10", c_short, 1),
("bitField11", c_short, 1)]
for field_descr in Flags_bits._fields_:
name = field_descr[0]
field = getattr(Flags_bits, name)
bfield_bits = field.size >> 16
if bfield_bits:
start = 8 * field.offset + field.size & 0xFFFF
stop = start + bfield_bits
else:
start = 8 * field.offset
stop = start + 8 * field.size
print("{:>10s}: bits {:>2d}:{:>2d}".format(
name, start, stop))
Output:
bitField1: bits 0: 1
bitField2: bits 1: 5
bitField3: bits 5:11
bitField4: bits 11:12
bitField5: bits 12:14
bitField6: bits 14:16
bitField7: bits 16:22
bitField8: bits 22:26
bitField9: bits 26:30
bitField10: bits 30:31
bitField11: bits 31:32
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With