当前位置: 首页 > 软件库 > 程序开发 > 常用工具包 >

namedstruct

二进制结构体解析库
授权协议 Apache
开发语言 Python
所属分类 程序开发、 常用工具包
软件类型 开源软件
地区 国产
投 递 者 乐正心思
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

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