欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > struct.pack——打包为二进制数据方法

struct.pack——打包为二进制数据方法

2025/2/23 1:22:56 来源:https://blog.csdn.net/lonelyxxyo/article/details/143702846  浏览:    关键词:struct.pack——打包为二进制数据方法

 struct模块可在python值和以python bytes对象表示的C结构体之间进行转换。

目录

基本语法

字节顺序、大小和对齐

示例代码

场景

转换逻辑:

如何转换

示例:从 Python 传到 C++ 

格式转换

分解来看

将字节数据转为 C++ 字符串字面量格式

方法 1:手动转换

方法 2:自动化工具(Python 脚本辅助)

背后的计算原理

总结


详细参考struct --- 将字节串解读为打包的二进制数据 — Python 3.13.0 文档

struct.pack 是 Python 中用于将数据打包成二进制格式的函数。

它主要用于处理 C 语言结构的数据,将 Python 的数据类型转换C 语言的二进制数据流。这个函数在处理文件或网络的二进制流时非常有用。

基本语法

struct.pack(format, v1, v2, ...)

其中,format参数指定了数据的格式,v1, v2, ... 是要打包的值。

格式字符串中的每个字符代表一种数据类型,常见的格式字符包括:

  • l:表示 long类型
  • d:表示 double类型
  • x:用于占位,不产生任何输出。
  • c:char,一个字节。
  • b:signed char,一个字节。
  • B:unsigned char,一个字节。
  • h:short,两个字节。
  • H:unsigned short,两个字节。
  • i:int,四个字节。
  • I:unsigned int,四个字节。
  • f:float,四个字节。
  • s:string,字符串。
# 例如:import struct# 打包 short, short, long 类型的数据
packed_data = struct.pack('hhl', 1, 2, 3)
print(packed_data) # 输出: b'\x01\x00\x02\x00\x03\x00\x00\x00'# 打包 char 和 int 类型的数据
packed_data = struct.pack('ci', b'*', 0x12131415)
print(packed_data) # 输出: b'*\x15\x14\x13\x12'# 可以通过len函数获取字节流的长度,并通过print函数打印输出。
print(len(packed_data))

字节顺序、大小和对齐

格式字符串还可以指定字节顺序、大小和对齐方式:

  • @ 本地字节顺序、大小和对齐

  • = 本地字节顺序,标准大小和对齐

  • < 小端字节顺序,标准大小和对齐

  • > 大端字节顺序,标准大小和对齐

  • ! 网络字节顺序(大端)

# 例如:import struct# 使用网络字节顺序(大端)打包数据
packed_data = struct.pack('!ihb', 1, 2, 3)
print(packed_data) # 输出: b'\x00\x00\x00\x01\x00\x02\x03'

示例代码

以下是一个完整的示例,展示了如何使用 struct.pack 和 struct.unpack: 

import struct# 打包数据
data = [1, 2, 3]
packed_data = struct.pack('!ihb', *data)
print(repr(packed_data)) # 输出: b'\x00\x00\x00\x01\x00\x02\x03'# 解包数据
unpacked_data = struct.unpack('!ihb', packed_data)
print(unpacked_data) # 输出: (1, 2, 3)

通过这些示例,可以看到 struct.pack 如何将 Python 数据类型转换为二进制数据流,并且可以通过 struct.unpack 将其还原为原始数据类型。这在处理需要与 C 语言程序或网络协议交互的数据时非常有用。


场景

在C++中,可以使用memcpy函数将数据从struct.pack的返回值复制到C++的内存中。

如果你要从 Python 中使用 struct.pack 生成更多不同类型的数据,然后在 C++ 中解析,可以参考以下示例:

import struct# 打包一个 int 和一个 float
data = struct.pack('if', 42, 3.14)
print(data)  # 输出: b'*\x00\x00\x00\xc3\xf5H@'

在 Python 中,struct.pack 函数返回的是字节序列(bytes 类型),通常在 Python 中以 b'...' 这种形式表示。

 ‘i’ 表示 4 字节的整数 (int):

  • 42 的十六进制表示是 0x2A,在内存中会表示为 \x2a\x00\x00\x00(小端序)。
  • b'*' 等价于 \x2a(即 42 的 ASCII 表示),剩下的 \x00\x00\x00 是填充高位。

‘f’ 表示 4 字节的浮点数 (float):

  • 3.14 的浮点表示在内存中是 \xc3\xf5\x48\x40(小端序)。

组合结果:struct.pack 返回的字节序列为:

  • b'\x2a\x00\x00\x00\xc3\xf5\x48\x40'。 
#include <iostream>
#include <cstring>int main() {// Python struct.pack('if', 42, 3.14) 的返回值char data[] = "\x2a\x00\x00\x00\xc3\xf5\x48\x40";int intValue;float floatValue;// 解析 int 值memcpy(&intValue, data, sizeof(intValue));// 解析 float 值memcpy(&floatValue, data + sizeof(intValue), sizeof(floatValue));std::cout << "int value: " << intValue << std::endl;      // 输出 42std::cout << "float value: " << floatValue << std::endl;  // 输出 3.14return 0;
}

运行上面的C++代码,将输出42,说明数据成功从Python的结构打包转换为C++的整型数据。

char data[] = "\x2a\x00\x00\x00\xc3\xf5\x48\x40";
转换逻辑:
  • \x2a 等价于 Python 中的 b'*',对应 ASCII 码为 42。
  • \x00\x00\x00 对应的是填充的高位,表示整数 42 在小端序下的表示方法。
  • \xc3\xf5\x48\x40 是浮点数 3.14 的 IEEE 754 表示,按照小端序排列。

如何转换

如果你想在 Python 和 C++ 之间传递数据,可以按照以下步骤进行:

  1. 在 Python 中使用 struct.pack 打包数据:

    打包后的数据是字节序列,比如 b'\x2a\x00\x00\x00\xc3\xf5\x48\x40'
  2. 在 C++ 中使用 memcpy 解包数据:

    你只需要将 Python 传过来的字节数据逐字节拷贝到 C++ 的内存中(如 char[] 数组),然后使用 memcpy 提取具体的类型值(如 intfloat)。

示例:从 Python 传到 C++ 

假设我们使用 Python 生成字节数据,并保存到文件中,然后在 C++ 中读取文件来解析。

import struct# 打包一个 int 和一个 float
data = struct.pack('if', 42, 3.14)
# 保存为文件,模拟传递数据
with open("data.bin", "wb") as f:f.write(data)
#include <iostream>
#include <fstream>
#include <cstring>int main() {// 打开文件读取字节序列std::ifstream file("data.bin", std::ios::binary);// 存储读取的数据char data[8];file.read(data, 8);file.close();int intValue;float floatValue;// 解析 int 值memcpy(&intValue, data, sizeof(intValue));// 解析 float 值memcpy(&floatValue, data + sizeof(intValue), sizeof(floatValue));std::cout << "int value: " << intValue << std::endl;      // 输出 42std::cout << "float value: " << floatValue << std::endl;  // 输出 3.14return 0;
}
  • 字节序列:Python 中的 b'*\x00\x00\x00\xc3\xf5H@' 和 C++ 中的 "\x2a\x00\x00\x00\xc3\xf5\x48\x40" 是等价的表示,都是小端序。
  • 转换struct.pack 生成的 bytes 在 Python 中直接是二进制格式,而在 C++ 中你可以使用字符串字面量(如 char[])来表示同样的二进制数据。
  • 跨语言一致性:这种表示方法在 Python 和 C++ 之间是一致的,使用 memcpy 解析即可,无需额外转换。

格式转换

如何从 Python 打印的字节序列得到 C++ 字符串字面量这种格式。

Python 中打印出的 b'*\x00\x00\x00\xc3\xf5H@' 实际上是字节序列的二进制表示形式,而 "\x2a\x00\x00\x00\xc3\xf5\x48\x40" 是 C++ 中的字符串字面量形式,两者是完全等价的,只是表示方式不同。 

分解来看

  1. b'*\x00\x00\x00'

    • * 是 ASCII 字符,对应的十六进制值为 \x2a
    • \x00\x00\x00 表示 3 个零字节。
    • 所以在 C++ 中等价为 "\x2a\x00\x00\x00"
  2. b'\xc3\xf5H@'

    • 这是浮点数 3.14 的 IEEE 754 表示。
    • 对应的字节顺序是:\xc3, \xf5, H, @
    • 其中 H 的 ASCII 值是 \x48@ 的 ASCII 值是 \x40
    • 所以在 C++ 中表示为 "\xc3\xf5\x48\x40"

将字节数据转为 C++ 字符串字面量格式

方法 1:手动转换

如果你看到 Python 中的输出 b'*\x00\x00\x00\xc3\xf5H@',可以手动按照以下规则转换:

  • 对于 *,查 ASCII 表知道十六进制为 0x2a,所以对应为 \x2a
  • 对于 \x00,就是字节 0,不需要转换。
  • 对于 H@,查 ASCII 表,分别对应 0x480x40,所以分别为 \x48\x40

这给出了 C++ 中的字符串字面量:"\x2a\x00\x00\x00\xc3\xf5\x48\x40"

方法 2:自动化工具(Python 脚本辅助)

如果你不想手动转换,可以写个 Python 脚本来输出这种格式:

import struct# 打包数据
data = struct.pack('if', 42, 3.14)# 将字节数据转为 C++ 字符串字面量格式
cpp_literal = ''.join(f'\\x{byte:02x}' for byte in data)
print(cpp_literal)  # 输出:\x2a\x00\x00\x00\xc3\xf5\x48\x40

你可以直接复制输出结果,并在 C++ 代码中使用。

背后的计算原理

对于浮点数 3.14,转换成 IEEE 754 单精度浮点表示法的小端序结果为 0x4048f5c3,对应字节序列为 \xc3\xf5\x48\x40

转换流程:

  • 3.14 的 IEEE 754 表示是 0x4048f5c3
  • 小端序表示时,最低有效字节放在最前面:
    • 低位字节是 0xc3(十进制 195)
    • 次低位字节是 0xf5(十进制 245)
    • 次高位字节是 0x48(ASCII 为 H
    • 高位字节是 0x40(ASCII 为 @

所以最终的字节序列为 "\xc3\xf5\x48\x40"

总结

通过 Python 的字节表示(如 b'*\x00\x00\x00\xc3\xf5H@'):

  1. 使用 ASCII 表或者查表方法手动转换字符到十六进制表示。
  2. 编写 Python 脚本自动转换为 C++ 字符串字面量格式("\x..")。
  3. 对于浮点数、整数等可以查阅 IEEE 754 或者利用 Python 自动解析。

这样,你就可以从 Python 的打印值快速得到 C++ 字符串字面量格式。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词