namedstruct 是一个解析二进制结构体的专用库,它不仅可以解析简单的 C 结构体,还可以支持变长结构体、可扩展的结构体之类复杂的情况。它被用来在 VLCP 中解析 OpenFlow(SDN 专用的二进制协议)。
使用这个库,你会发现,即便是像 OpenFlow 这样复杂的协议,实际上只需要将对应的 C 程序的头文件(比如openflow.h)按照相应的规则进行修改,添加一些简单的参数说明结构体之间的关系,就可以用一行代码将它完整解析出来,或者用一行代码生成出相应的结构体。
可以使用pip安装:
pip install nstruct
###### BASIC STRUCT ##### from namedstruct import * mytype = nstruct((uint16, 'myshort'), # unsigned short int (uint8, 'mybyte'), # unsigned char (uint8,), # a padding byte of unsigned char (char[5], 'mystr'), # a 16-byte bytes string (uint8,), (uint16[5], 'myarray'), # name = 'mytype', padding = 1) # Create an object obj0 = mytype() # Access a field s = obj0.myshort obj0.myshort = 12 # Create an object with the specified fields initialized obj1 = mytype(myshort = 2, mystr = b'123', myarray = [1,2,3,4,5]) # Unpack an object from stream, return the object and bytes size used obj2,size = mytype.parse(b'\x00\x02\x01\x00123\x00\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05') # Unpack an object from packed bytes obj3 = mytype.create(b'\x00\x02\x01\x00123\x00\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05') # Estimate the struct size size = len(obj0) # Estimate the struct size excludes automatic padding bytes size2 = obj0._realsize() # Pack the object b = obj0._tobytes() b2 = mytype.tobytes(obj0) # Use the type in other structs mytype2 = nstruct((mytype, 'mydata'), (mytype[4], 'mystructarray'), name = 'mytype2', padding = 1) obj4 = mytype2() obj4.mydata.myshort = 12 obj4.mystructarray[0].mybyte = 7 b3 = obj4._tobytes() ###### VARIABLE LENGTH TYPES ##### my_unsize_struct = nstruct((uint16, 'length'), (raw, 'data'), padding = 1, name = 'my_unsize_struct') """ >>> my_unsize_struct.create(b'\x00\x07abcde').data b'abcde' >>> my_unsize_struct.parse(b'\x00\x07abcde')[0].data b'' """ my_size_struct = nstruct((uint16, 'length'), (raw, 'data'), padding = 1, name = 'my_size_struct', prepack = packrealsize('length'), size = lambda x: x.length) """ packrealsize('length') is equivalent to: def _packsize(x): x.length = x._realsize() """ """ >>> my_unsize_struct(data = b'abcde')._tobytes() b'\x00\x07abcde' >>> my_unsize_struct.parse(b'\x00\x07abcde')[0].data b'abcde' """ ##### EXTENDING ##### my_base = nstruct((uint16, 'length'), (uint8, 'type'), (uint8, 'basedata'), name = 'my_base', size = lambda x: x.length, prepack = packrealsize('length'), padding = 4) my_child1 = nstruct((uint16, 'data1'), (uint8, 'data2'), name = 'my_child1', base = my_base, criteria = lambda x: x.type == 1, init = packvalue(1, 'type')) my_child2 = nstruct((uint32, 'data3'), name = 'my_child2', base = my_base, criteria = lambda x: x.type == 2, init = packvalue(2, 'type')) """ Fields and most base class options are inherited, e.g. size, prepack, padding >>> my_child1(basedata = 1, data1 = 2, data2 = 3)._tobytes() b'\x00\x07\x01\x01\x00\x02\x03\x00' >>> my_child2(basedata = 1, data3 = 4)._tobytes() b'\x00\x08\x02\x01\x00\x00\x00\x04' """ # Fields in child classes are automatically parsed when the type is determined obj1, _ = my_base.parse(b'\x00\x07\x01\x01\x00\x02\x03\x00') """ >>> obj1.basedata 1 >>> obj1.data1 2 >>> obj1.data2 3 >>> obj1._gettype() my_child1 """ # Base type can be used in fields or arrays of other structs my_base_array = nstruct((uint16, 'total_len'), (my_base[0], 'array'), name = 'my_base_array', padding = 1, size = lambda x: x.total_len, prepack = packrealsize('total_len')) obj2 = my_base_array() obj2.array.append(my_child1(data1 = 1, data2 = 2, basedata = 3)) obj2.array.append(my_child2(data3 = 4, basedata = 5)) """ >>> obj2._tobytes() b'\x00\x12\x00\x07\x01\x03\x00\x01\x02\x00\x00\x08\x02\x05\x00\x00\x00\x04' """ obj3, _ = my_base_array.parse(b'\x00\x12\x00\x07\x01\x03\x00\x01\x02\x00\x00\x08\x02\x05\x00\x00\x00\x04') """ >>> obj3.array[0].data2 2 """
类似地,解构 struct 如下所示: fn main() { struct Foo { x: (u32, u32), y: u32 } // 解构结构体的成员 let foo = Foo { x: (1, 2), y: 3 }; let Foo { x: (a, b), y } = foo; println!("a = {}, b = {}, y = {
我有: 产生项目的许多线程 要点: 生成项目比更新GUI快得多 我们可能有很多新项目同时生产 每个项目生产后都必须进行一次GUI更新 如果产品同时发生,所有产品必须只进行一次更新...没有必要多次刷新GUI 我想我正在寻找一些实现二进制信号量的标准结构,其中最大许可数是1,这样工作人员就可以调用多个,而不会相互阻塞,如果调用了一个,那么: 如果GUI线程正在睡眠= 代码应如下所示: 请注意,使用1
问题内容: 我有一个混合二进制数据和文本数据的文件。我想通过正则表达式解析它,但出现此错误: 我猜该消息意味着Python不想解析二进制文件。我正在打开带有标志的文件。 如何在Python中使用正则表达式解析二进制文件? 编辑: 我正在使用Python 3.2.0 问题答案: 我认为您使用Python 3。 1.以 二进制模式 打开文件很简单但是很微妙。与在文本模式下打开它的唯一区别是mode参数
本文向大家介绍解析Python中的二进制位运算符,包括了解析Python中的二进制位运算符的使用技巧和注意事项,需要的朋友参考一下 下表列出了所有的Python语言的支持位运算符。假设变量a持有60和变量b持有13,则: 示例: 试试下面的例子就明白了所有的Python编程语言提供了位运算符: 当执行上面的程序它会产生以下结果:
结构体是MATLAB的多维数组,其元素取决于原文的域指示符。例如, S.name = 'Ed Plum'; S.score = 83; S.grade = 'B+' 创建一个含三个域的标量结构体。 S = name: 'Ed Plum' score: 83 grade: 'B+' 和MATLAB的其他一切一样,结构体是数组,故可以插入附加元素。在此情况下,数组的每个
4.4. 结构体 结构体是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体。每个值称为结构体的成员。用结构体的经典案例处理公司的员工信息,每个员工信息包含一个唯一的员工编号、员工的名字、家庭住址、出生日期、工作岗位、薪资、上级领导等等。所有的这些信息都需要绑定到一个实体中,可以作为一个整体单元被复制,作为函数的参数或返回值,或者是被存储到数组中,等等。 下面两个语句声明了一个叫Emplo