Как элегантно отправлять / получать большую C-структуру с помощью Python?

Я начал писать клиентское приложение Python 3.x. Серверное приложение уже существует и написано на C. Сервер предоставляет заголовочный файл C с определением двух структур, используемых для отправки и приема данных через UDP (я использую модуль socket Python). Проблема в том, что структуры C довольно большие (около 200 элементов каждый). Если я использую struct модуль Python для упаковки / распаковки данных, не очень элегантное решение будет упаковывать / распаковывать 200 элементов вручную, например:

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

Кроме того, я хочу иметь доступ к полученным / отправленным элементам в Python с использованием синтаксиса типа C. Например, если я делаю на стороне сервера C

 send.data.pos = pos; 

было бы неплохо (наиболее естественно), если я могу получить доступ к переменной pos в клиентской части Python следующим образом:

 pos = recv.data.pos 

Обратите внимание, что вопрос заключается не в том, как автоматически писать структуру в Python из заголовочного файла, как в этом потоке (у меня нет проблем при написании каждого поля структуры один за другим в Python), а скорее, что было бы лучшим способом организовать данные на Python (например, в классах, используя словари и т. д.), которые позволят мне использовать возможности Python и упростить код и легко получить доступ к данным (я бы предпочел использовать только стандартные модули Python, без внешнего программного обеспечения). Какой был бы самый элегантный способ достичь этого?

Попробуйте это – работает с 2,7 и 3,2.

Автор сценария:

 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 

Вы можете написать класс, который имеет функции-члены, чтобы упаковать / распаковать данные в атрибуты класса / из класса, используя struct.pack и т. Д.

Я бы предложил посмотреть на Construct . Но я не думаю, что он портирован на Python 3.x. Construct был на паузе в течение некоторого времени, но недавно был подхвачен новым разработчиком, поэтому, возможно, он вскоре сможет поддерживать Python 3.x.

Возможно, вы сможете использовать dpkt как простой способ доступа к пакетным данным. Взгляните сюда на примеры использования. Для простого примера:

 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)