1
votes

I would like to construct an unsigned 32-bit int using Python3 ctypes bit field, as follows:

c_uint = ctypes.c_uint32

class Flags_bits(ctypes.LittleEndianStructure):
    _fields_ = [ 
            ("a", c_uint, 4),
            ("b", c_uint, 4),
            ("c", c_uint, 4),
            ("d", c_uint, 4),
            ("e", c_uint, 4),
            ("f", c_uint, 4),
            ("g", c_uint, 4),
            ("h", c_uint, 4)]

When I substitute Flags_bits with specific integer values,

aa = Flags_bits(1,2,3,4,5,6,7,8)
print(hexlify(aa).decode('utf-8'))

The output is

21436587

I was expecting an output like

87654321 # binary of 1000 0111 0110 0101 0100 0011 0010 0001

Since Little-endian constructs bits starting with the low bit. How can I obtain the expected output? Is there anything I did wrong? Could someone be so kind to help me? Thanks in advance!

1

1 Answers

3
votes

It IS stored little-endian. The binascii.hexlify function reads the value as a set of bytes, and returns a string of those bytes. It's not treating them as an integer. As bytes, the values are 21 43 65 87. Unless you treat a set of bytes as a multi-byte unit, endianness does not apply.

If you want to see the value as a 32-bit integer, do this, which results in 87654321:

import struct
...
aa = Flags_bits(1,2,3,4,5,6,7,8)
aa_int = struct.unpack('I',aa)[0]
print(hex(aa_int))

Bitfield structures are problematic, even in C. Honestly, in many cases it's way easier to shift and mask:

def Flags_bits(*data):
    val = 0
    for n in reversed(data):
        val = (val << 4) | n
    return val