NGC13009/pycstructdataparser_lib
GitHub: NGC13009/pycstructdataparser_lib
直接从 C/C++ 头文件文本解析 struct 定义,在 Python 中实现二进制数据的自动序列化与反序列化,无需手动编写样板代码。
Stars: 0 | Forks: 0
# pycstructdataparser-lib
[中文说明书] | English
**直接从 C/C++ 头文件文本中自动解析 struct 定义并在 Python 中处理二进制数据** — 无需编译,无需手动编写 `ctypes.Structure` 子类,零样板代码。通过自动化的数据解包/打包,实现 C/C++ 与 Python 之间的无缝数据传输。 ## 概述 具体而言,本包使用 Python 内置的 `ctypes` 模块,从 C/C++ `.h` 文件中解析 struct 定义并处理其对应的二进制数据。您只需提供头文件中的 struct 定义文本,即可完成二进制数据的序列化 和反序列化。 借助此模块,用户无需在每次数据字段定义更改时重写 Python 的 CRUD 代码——打包/解包方法可以直接从 `.h` 文件生成。 非常适合 Python 与 C/C++ 程序之间的数据通信,例如: - TCP/UDP 比特流消息传输 - 本地二进制数据文件读写(`.bin` 文件、`.dat` 文件等) - 数据协议频繁变更的项目场景 - 协议快速迭代的开发阶段 ## 快速开始 直接从 PyPI 安装: ``` pip install pycstructdataparser-lib ``` 然后即可使用。以下代码演示了完整的核心工作流程: ``` from pycstructdataparser_lib import CStructParser, pack, unpack # 1. 准备 C struct 定义文本 header = ''' #pragma pack(push, 1) typedef struct { unsigned char id; unsigned int value; float data[4]; } MyStruct; #pragma pack(pop) ''' # 2. 解析头文件并注册 struct 类型 parser = CStructParser() parser.parse(header) # 3. 将 Python 字典 Pack 为二进制字节(序列化) original = {'id': 10, 'value': 12345, 'data': [1.0, 2.0, 3.0, 4.0]} raw = pack(parser, 'MyStruct', original) print(f"pack output: {len(raw)} bytes") # 4. 将二进制字节 Unpack 回 Python 字典(反序列化) restored = unpack(parser, 'MyStruct', raw) print(restored) ``` 预期输出: ``` pack output: 21 bytes {'id': 10, 'value': 12345, 'data': [1.0, 2.0, 3.0, 4.0]} ``` ## 特性 - **位域支持**:解析形如 `unsigned char field : 2;` 的位域声明 - **C 头文件解析**:识别 `typedef struct { … } TypeName;` 块,自动提取 struct 定义 - **`#pragma pack` 支持**:正确处理 `#pragma pack(push, N)` 和 `#pragma pack(pop)` 对齐栈 - **数组支持**:处理固定大小的数组,例如 `Type array[10];` - **嵌套 struct**:支持在其他 struct 中使用 struct 类型作为字段 - **序列化**:将 Python 字典转换为 C struct 的二进制字节 - **反序列化**:将原始字节解析回嵌套的 Python 字典 - **严格模式**:在打包时可选验证是否包含所有非位域字段,以及值域检查(位域溢出、整数类型范围) ## 安装方法 ### 方法一:PyPI 安装(推荐) ``` pip install pycstructdataparser-lib ``` ### 方法二:从 GitHub 仓库本地使用 克隆仓库后,您可以以可编辑模式安装,或将仓库目录添加到 Python 搜索路径中。 **可编辑模式安装(推荐)**: ``` git clone https://github.com/NGC13009/pycstructdataparser_lib.git cd pycstructdataparser_lib pip install -e . ``` **在代码中直接添加路径**(无需安装): ``` import sys sys.path.insert(0, '/path/to/pycstructdataparser_lib') from pycstructdataparser_lib import CStructParser, pack, unpack ``` ### 方法三:通过 .whl 包安装 从 [Release 页面](https://github.com/NGC13009/pycstructdataparser_lib/releases)下载最新的 `.whl` 文件,然后运行: ``` pip install pycstructdataparser_lib-*.whl ``` ### 方法四:手动构建 ``` pip install build # Build toolchain git clone https://github.com/NGC13009/pycstructdataparser_lib.git cd pycstructdataparser_lib python -m build pip install dist/pycstructdataparser_lib-*.whl ``` ## 使用指南 ### 核心 API | 函数 / 方法 | 描述 | |------------------|-------------| | `CStructParser()` | 创建一个解析器实例 | | `parser.parse(header_content)` | 解析 C/C++ 头文件字符串,注册其中定义的 struct 类型 | | `parser.get_struct_class(name)` | 通过类型名检索相应的 `ctypes.Structure` 子类 | | `parser.struct_classes` | 返回包含所有已注册 struct 类的字典(属性) | | `pack(parser, struct_name, data_dict, strict=True)` | 将 Python 字典序列化为二进制字节序列 | | `unpack(parser, struct_name, data)` | 将二进制字节序列反序列化为 Python 字典 | ### 基本用法:直接处理头文件字符串和二进制流 本库的核心工作流程是:将 C 头文件中的 struct 定义文本传递给 `CStructParser.parse()`,然后使用 `pack()` 和 `unpack()` 在 Python 字典和二进制字节之间进行转换。有关详细信息,请参阅上面的“快速开始”示例。 ### 读/写本地二进制文件 以 `test_roundtrip.py` 为参考,典型的工作流程如下: 1. 读取头文件 → 使用 `CStructParser` 解析 2. 构造一个 Python 字典作为测试数据 3. 调用 `pack()` 将字典序列化为二进制字节,然后写入 `.bin` 文件 4. 从 `.bin` 文件中读取字节,调用 `unpack()` 将其还原为字典 5. 将原始数据与还原后的数据进行比较以验证一致性 有关详细的实现,请参阅本仓库中的 [`test_roundtrip.py`](test_roundtrip.py) 文件。该文件还演示了将字典保存为 JSON 文件以及从 JSON 加载后进行打包等操作。 ### 在网络通信中的应用 在 TCP/UDP 编程中,`pack()` 的输出可以直接发送到 socket,而从 socket 接收到的字节可以直接传递给 `unpack()`。由于该库的输入和输出均为 `bytes` 类型,因此天然兼容标准的 socket 接口。特定于业务的逻辑(例如处理消息边界和字节序协商)必须由用户根据实际协议自行实现。 ## API 参考 ### `CStructParser` ``` class CStructParser: def __init__(self) -> None: ... def parse(self, header_content: str) -> None: ... def get_struct_class(self, name: str) -> type: ... @property def struct_classes(self) -> Dict[str, type]: ... ``` **`parse(header_content)`** 解析 C/C++ 头文件字符串,提取所有 `typedef struct { … } Name;` 块,并为每个 struct 动态创建一个 `ctypes.Structure` 子类。 支持的特性: - C 风格注释(`//` 和 `/* … */`) - `#pragma pack(push, N)` / `#pragma pack(pop)` 对齐指令 - 标准 C 基本类型、位域、固定大小的数组 - 嵌套的命名 struct(优先处理前向引用) **`get_struct_class(name)`** 返回与指定名称对应的 `ctypes.Structure` 子类。如果名称未注册,则引发 `ValueError`。 **`struct_classes`** 返回包含所有已注册 struct 类的字典,以 struct 名称为键,相应的 `ctypes.Structure` 子类为值。 ### `pack(parser, struct_name, data_dict, strict=True)` ``` def pack( parser: CStructParser, struct_name: str, data_dict: Dict[str, Any], strict: bool = True, ) -> bytes: ... ``` 将 Python 字典序列化为对应于 C struct 的二进制字节。 - `parser`:已调用过 `parse()` 的 `CStructParser` 实例。 - `struct_name`:目标 struct 类型名称。 - `data_dict`:字段名称到字段值的映射字典。 - `strict`:如果为 `True`(默认): - 当缺少 **非位域** 字段时引发 `ValueError`。 - 对每个标量值执行 **值域验证**:位域值必须在 `[0, 2^width - 1]` 范围内;整数类型必须在其类型的最小/最大范围内(例如 `uint8_t` → `[0, 255]`,`int32_t` → `[-2147483648, 2147483647]`);浮点数和 struct 类型不进行范围检查。 - 如果为 `False`,缺失的字段将被静默填充为 0,并且不执行值域检查。 ### `unpack(parser, struct_name, data)` ``` def unpack( parser: CStructParser, struct_name: str, data: bytes, ) -> Dict[str, Any]: ... ``` 将原始二进制字节反序列化为嵌套的 Python 字典。 - `parser`:已调用过 `parse()` 的 `CStructParser` 实例。 - `struct_name`:目标 struct 类型名称。 - `data`:要解码的二进制字节序列。 ## 支持的 C 类型映射 | C 类型 | ctypes 类型 | |--------|-------------| | `char`, `signed char` | `c_byte` | | `unsigned char` | `c_ubyte` | | `short`, `short int` | `c_short` | | `unsigned short` | `c_ushort` | | `int`, `signed int` | `c_int` | | `unsigned int` | `c_uint` | | `long`, `long int` | `c_long` | | `unsigned long` | `c_ulong` | | `long long`, `long long int` | `c_longlong` | | `unsigned long long` | `c_ulonglong` | | `float` | `c_float` | | `double` | `c_double` | | `long double` | `c_longdouble` | | `int8_t` .. `uint64_t` | `c_int8` .. `c_uint64` | | `float32_t` | `c_float` | | `float64_t` | `c_double` | ## 与常见方法的比较 | 特性 | `struct` 模块 | `ctypes.Structure` | `construct` 库 | cStructDataParser | |---------|:---:|:---:|:---:|:---:| | 直接从头文件文本解析 | ❌ | ❌ | ❌ | ✅ | | 自动处理 `#pragma pack` 对齐 | ❌ | ❌ | ❌ | ✅ | | 位域支持 | ❌ | ✅ | ✅ | ✅ | | 嵌套 struct | ❌ | 需手动编写 | ✅ | ✅ | | 无外部依赖(纯 Python) | ✅ | ✅ | ✅ | ✅ | ## 已知限制 - 目前仅支持 **小端序** 字节序;尚未处理大端序场景 - 如果设备使用大端序,则需要在调用 `pack()` / `unpack()` 之前/之后进行额外的字节序处理 ## 许可证 本项目采用 [GPLv3.0](https://www.gnu.org/licenses/gpl-3.0.en.html) 授权。 [NGC13009/pycstructdataparser_lib.git](https://github.com/NGC13009/pycstructdataparser_lib.git)标签:C/C++, ctypes, PyPI, Python, TCP/UDP, 事务性I/O, 二进制协议, 二进制数据, 二进制解析, 内核驱动, 反序列化, 头文件解析, 序列化, 开源库, 打包, 搜索引擎爬虫, 数据交互, 数据反序列化, 数据序列化, 数据转换, 文件读写, 无后门, 结构体映射, 结构体解析, 网络协议, 自动化解析, 解包, 跨语言通信, 逆向工具