On an embedded device running a C application, I have defined this struct:
struct TestStruct { float first; int second; char third; };
On request, I send this struct via sockets:
else if(strcmp(str, "Get Stru") == 0) { TestStruct testStruct; testStruct.first = 1.2; testStruct.second = 42; testStruct.third = 'A'; INT32 sendDataLength = send(m_Socket, (char *)(&testStruct), sizeof(testStruct), 0); }
and read it from a Python script on my desktop:
import struct import socket from ctypes import * class YourStruct(Structure): _fields_ = [('v', c_float), ('t', c_int), ('c', c_char)] s = socket.socket() host = '127.0.0.1' port = 1234 s.connect((host, port)) s.send('Get Stru'.encode()) data = s.recv(20) print(data) x = YourStruct()
This is the data printed to console on my desktop:
How can i reassemble the data
into a YourStruct
?
Note that the embedded device uses little endian, so I have had to use struct.unpack("<" + "f" * 2048, data)
to reassemble an array of floats.
Advertisement
Answer
[Python.Docs]: struct – Interpret bytes as packed binary data contains all the needed intel.
code00.py:
#!/usr/bin/env python import ctypes as ct import struct import sys class SampleStruct(ct.Structure): _fields_ = ( ("v", ct.c_float), ("t", ct.c_int), ("c", ct.c_char), ) def main(*argv): data = b"x9ax99x99?*x00x00x00Axbexadxde" x = SampleStruct() fmt = "<fic" fmt_size = struct.calcsize(fmt) x.v, x.t, x.c = struct.unpack(fmt, data[:fmt_size]) print("Fieldsn v: {:f}n t: {:d}n c: {:s}".format(x.v, x.t, x.c.decode())) if __name__ == "__main__": print("Python {:s} {:03d}bit on {:s}n".format(" ".join(elem.strip() for elem in sys.version.split("n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform)) rc = main(*sys.argv[1:]) print("nDone.") sys.exit(rc)
Notes:
Starting from the point where the data (data) was received from the socket
The format passed to struct.unpack (fmt arg) tells it how the data is organized: in our case it’s
"<fic"
: float, int, char (preceded by the little endian marker)Also calculating the size (in bytes) of data that the format requires: it’s 9 (4 + 4 + 1). data has 12 bytes, so ignoring the last 3, otherwise struct.unpack will spit struct.error
Check [SO]: Python struct.pack() behavior for more details on struct.pack
Output:
[cfati@CFATI-5510-0:e:WorkDevStackOverflowq048822543]> "e:WorkDevVEnvspy_pc064_03.07.09_test0Scriptspython.exe" ./code00.py Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18) [MSC v.1900 64 bit (AMD64)] 064bit on win32 Fields v: 1.200000 t: 42 c: A Done.