So I am trying to do a bitmap. The data comes from a device as a 32bit number and each bit means something. So I was playing around with ctype Structures and Unions. Trying to do the classic int in and it maps to the individual bits.
from ctypes import * class Bits(Structure): _fields_ = [("Bit_0", c_bool), ("Bit_1", c_bool), ("Bit_2", c_bool), ("Bit_3", c_bool), ("Bit_4", c_bool), ("Bit_5", c_bool), ("Bit_6", c_bool), ("Bit_7", c_bool), ("Bit_8", c_bool), ("Bit_9", c_bool), ("Bit_10", c_bool), ("Bit_11", c_bool), ("Bit_12", c_bool), ("Bit_13", c_bool), ("Bit_14", c_bool), ("Bit_15", c_bool), ("Bit_16", c_bool), ("Bit_17", c_bool), ("Bit_18", c_bool), ("Bit_19", c_bool), ("Bit_20", c_bool), ("Bit_21", c_bool), ("Bit_22", c_bool), ("Bit_23", c_bool), ("Bit_24", c_bool), ("Bit_25", c_bool), ("Bit_26", c_bool), ("Bit_27", c_bool), ("Bit_28", c_bool), ("Bit_29", c_bool), ("Bit_30", c_bool), ("Bit_31", c_bool), ] def return_dic(self): dic = {} for field in self._fields_: dic[field[0]] = getattr(self, field[0]) return(dic) class Int(Structure): _fields_ = [("Value", c_int32)] class union(Union): _fields_ = [("Descriptor", Int),("Bits", Bits)] test = union(Int(0b01111111111111111111111111111111)) print("{0:b}".format(test.Descriptor.Value)) dic = test.Bits.return_dic() for x in dic.keys(): print("{0} : {1:b}".format(x,dic[x]))
and this output. This first line is the 32bit value and the rest are individual bits.
1111111111111111111111111111111 Bit_0 : 1 Bit_1 : 1 Bit_2 : 1 Bit_3 : 1 Bit_4 : 0 Bit_5 : 0 Bit_6 : 0 Bit_7 : 0 Bit_8 : 0 Bit_9 : 0 Bit_10 : 0 Bit_11 : 0 Bit_12 : 0 Bit_13 : 0 Bit_14 : 0 Bit_15 : 0 Bit_16 : 0 Bit_17 : 0 Bit_18 : 0 Bit_19 : 0 Bit_20 : 0 Bit_21 : 0 Bit_22 : 0 Bit_23 : 0 Bit_24 : 0 Bit_25 : 0 Bit_26 : 0 Bit_27 : 0 Bit_28 : 0 Bit_29 : 0 Bit_30 : 0 Bit_31 : 0
Why are the bits 4 – 31 not being set? and bit 0 – 3 are behaving very weird too
Advertisement
Answer
c_bool
is one byte in size and prints 0
for zero and 1
for non-zero. You can see that the size in bytes for the structures are incorrect:
>>> sizeof(Bits) 32 >>> sizeof(Int) 4 >>> sizeof(union) 32
Since Value
is a 4-byte integer and all four bytes are non-zero the first four byte-sized c_bool
fields in the union print 1
.
To specify bit fields correctly, specify a 3rd parameter with the number of bits to use. See Bit fields in structures and unions in the ctypes documentation.
from ctypes import * class Bits(Structure): _fields_ = [('Bit_0', c_uint32, 1), # Use 1 bit of an unsigned 32-bit integer. ('Bit_1', c_uint32, 1), # etc. ('Bit_2', c_uint32, 1), ('Bit_3', c_uint32, 1), ('Bit_4', c_uint32, 1), ('Bit_5', c_uint32, 1), ('Bit_6', c_uint32, 1), ('Bit_7', c_uint32, 1), ('Bit_8', c_uint32, 1), ('Bit_9', c_uint32, 1), ('Bit_10', c_uint32, 1), ('Bit_11', c_uint32, 1), ('Bit_12', c_uint32, 1), ('Bit_13', c_uint32, 1), ('Bit_14', c_uint32, 1), ('Bit_15', c_uint32, 1), ('Bit_16', c_uint32, 1), ('Bit_17', c_uint32, 1), ('Bit_18', c_uint32, 1), ('Bit_19', c_uint32, 1), ('Bit_20', c_uint32, 1), ('Bit_21', c_uint32, 1), ('Bit_22', c_uint32, 1), ('Bit_23', c_uint32, 1), ('Bit_24', c_uint32, 1), ('Bit_25', c_uint32, 1), ('Bit_26', c_uint32, 1), ('Bit_27', c_uint32, 1), ('Bit_28', c_uint32, 1), ('Bit_29', c_uint32, 1), ('Bit_30', c_uint32, 1), ('Bit_31', c_uint32, 1)] def return_dic(self): dic = {} for field in self._fields_: dic[field[0]] = getattr(self, field[0]) return(dic) class Int(Structure): _fields_ = [('Value', c_uint32)] class union(Union): _fields_ = [('Descriptor', Int),('Bits', Bits)] test = union(Int(0x87654321)) print('{0:b}'.format(test.Descriptor.Value)) dic = test.Bits.return_dic() for x in dic.keys(): print('{0} : {1:b}'.format(x,dic[x]))
Output:
10000111011001010100001100100001 Bit_0 : 1 Bit_1 : 0 Bit_2 : 0 Bit_3 : 0 Bit_4 : 0 Bit_5 : 1 Bit_6 : 0 Bit_7 : 0 Bit_8 : 1 Bit_9 : 1 Bit_10 : 0 Bit_11 : 0 Bit_12 : 0 Bit_13 : 0 Bit_14 : 1 Bit_15 : 0 Bit_16 : 1 Bit_17 : 0 Bit_18 : 1 Bit_19 : 0 Bit_20 : 0 Bit_21 : 1 Bit_22 : 1 Bit_23 : 0 Bit_24 : 1 Bit_25 : 1 Bit_26 : 1 Bit_27 : 0 Bit_28 : 0 Bit_29 : 0 Bit_30 : 0 Bit_31 : 1