How to elegantly send / receive a large C-structure using Python?

I started writing a Python 3.x client application. The server application already exists and is written in C. The server provides a C header file with the definition of two structures used to send and receive data via UDP (I use the Python module socket). The problem is that C structures are quite large (about 200 elements each). If I use the Python module structfor packing / unpacking data, a not-so-elegant solution would be to pack / unpack 200 elements manually, for example:

struct.pack('H...I', data1, ..., data200)

Also, I want to have access to the received / sent items in Python using type C syntax. For example, if I do C server side

send.data.pos = pos;

it would be nice (most natural) if I can access the variable poson the Python client side as follows:

pos = recv.data.pos

Please note that the question is not how to automatically write the structure in Python from the header file, as in this thread (I have no problem writing each field of the structure one by one in Python), but rather what would be the best way organize data in Python (for example, in classes, using dictionaries, etc.), which will allow me to use Python functions and make the code simpler, and the data is easy (I would prefer to use only standard Python modules, without external software). What would be the most elegant way to achieve this?

+3
source share
3

- 2,7 3,2.

Script:

import struct, collections

class CStruct(object):

    def __init__(self, typename, format_defn, lead_char="!"):
        self.names = []
        fmts = [lead_char]
        for line in format_defn.splitlines():
            name, fmt = line.split()
            self.names.append(name)
            fmts.append(fmt)
        self.formatstr = ''.join(fmts)
        self.struct = struct.Struct(self.formatstr)
        self.named_tuple_class = collections.namedtuple(typename, self.names)

    def object_from_bytes(self, byte_str):
        atuple = self.struct.unpack(byte_str)
        return self.named_tuple_class._make(atuple)

if __name__ == "__main__":
    # do this once
    pkt_def = """\
        u1 B
        u2 H
        u4 I"""
    cs = CStruct("Packet1", pkt_def)
    # do this once per incoming packet
    o = cs.object_from_bytes(b"\xF1\x00\xF2\x00\x00\x00\xF4")
    print(o)
    print(o.u4)

:

Packet1(u1=241, u2=242, u4=244)
244
+1

, - / / struct.pack ..

Construct. , Python 3.x. Construct , , , , Python 3.x.

+1

You may be able to use dpkt as an easy way to access packet data. Look here for usage examples. For a simple example:

class Foo(dpkt.Packet):
    __hdr__ = (('type', 'B', 0),
               ('size', 'B', 0))

data = get_udp_message()
foo = Foo(data)
if foo.size != len(data):
    print "Bad size in header"
if foo.type == 3:
    parse_payload(foo.data)
+1
source

All Articles