VoidShredder VoidShredder - 7 days ago 6
Python Question

Unpacking a struct containing a boolean in Python

So I'm currently trying to unpack a struct that has the following format, written in C:

{
volatile bool
volatile float
bool
}


I have sent this out using the UDP library

Udp.write(((byte*)&pm), sizeof(struct PressureMonitor));


And on the other end, I am using Python to receive the Datapacket.

import socket
import time
import struct

UDP_IP = '192.168.1.222'
UDP_PORT = 8742

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(1024)
print(len(data))
print(struct.unpack('cfc',data))
time.sleep(.01)


len(data) gives me a length of 6, which is expected. However, I'm running into issues on the next line. Given that the struct is formatted boolean, float, boolean, 'cfc' should be the right format string. However, it is erroring and telling me that it should be a 9 byte piece of data, which is completely baffling me. I could (as suggested by someone) simply replace the struct by a float/double array, but I feel like it would be better for me if I can figure out what is wrong with this.

Answer

You need to tell struct.unpack that your data isn't padded.

The format string 'cfc' doesn't contain a byte order / alignment character, which is equivalent to specifying '@' as the byte order / alignment character, so you get native byte ordering and native alignment. Float data is 4 bytes wide and should be aligned on a 4 byte boundary, but since you have a one byte bool before your float 3 padding bytes get added after that first bool to ensure the float is correctly aligned.

You can specify native byte ordering with no padding with a '=cfc' format string. But it would be better to explicitly indicate the correct byte ordering. If the data is being sent from an Intel machine, that would be '<cfc'. Please see Byte Order, Size, and Alignment in the struct module docs for details.