Python 中具有类似-c 属性的结构
Structure with attribute like-c in Python
我想在 C 中创建类似于结构的东西,但在 Python 中。具体来说,我想这样:
typedef struct __attribute__((__packed__))
{
float x[4];
uint8 y;
int z;
} structName;
在 Python 中。我在某处读到我可以使用命名元组但想避免填充,但我不知道如何在 Python 中进行填充。谁能告诉我该怎么做?我会在UDP通信中使用它。
如果你想序列化(例如:保存到文件或通过网络发送),你应该检查 struct 库基本上你可以定义如何保存你的数据,多少字节和顺序。
您可以在 python 中使用 class 来表示您的结构,并添加两个函数以将其打包成较小的二进制数据,并在您再次需要时从中解压
你的例子应该是:
import struct
class StructName():
def __init__(self, xs=None, y=None, z=None):
self.xs = xs
self.y = y
self.z = z
def pack(self):
return struct.pack("!4fBi", *self.xs, self.y, self.z)
def unpack(self, packed_bytes):
*self.xs, self.y, self.z = struct.unpack("!4fBi", packed_bytes)
if __name__ == "__main__":
s = StructName([1.0, 0.5, 2.0, 0.], 255, 42)
tmp = StructName()
bytedata = s.pack()
print("s", s.xs, s.y, s.z) # s [1.0, 0.5, 2.0, 0.0] 255 42
print(len(bytedata), bytedata) # 21 b'\x00\x00\x80?\x00\x00\x00?\x00\x00\x00@\x00\x00\x00\x00\xff\x00\x00\x00*\x00\x00\x00'
tmp.unpack(bytedata) # fill data into tmp class
tmp.xs[0] = 42.5
print("tmp", tmp.xs, tmp.y, tmp.z) # tmp [42.5, 0.5, 2.0, 0.0] 255 42
pack
和 unpack
函数中的格式字符串是 "!4fBi" 其中:
- ! - 使用网络字节序 (bigendian)
- 4f - 四个浮点数(4*4 字节)
- B - 一个无符号字符(1 字节)
- i - 一个有符号整数(4 字节)
有关更多信息,请查看此部分:Format Characters
在已接受答案的评论部分回答评论
import re
import struct
def get_values_from_binary(format_str, bin_data):
val_regex = re.compile(r"[a-zA-Z]([0-9]+)?")
ls = struct.unpack(format_str, bin_data)
res = []
i = 0
for m in val_regex.finditer(format_str):
groups = m.groups()
current_length = 1
if groups is not None and groups[0] is not None:
current_length = int(groups[0])
res.append(ls[i:i + current_length])
i += current_length
return res
if __name__ == "__main__":
f_str = "<I7f7f7f3f4ffI"
data = [0]*7 + [0.3]*7 + [0.5]*7 + [0.9]*3 + [1.0]*4 + [2.5, 3.5, 1]
print(data)
bindata = struct.pack(f_str, *data)
unpacked_data = get_values_from_binary(f_str, bindata)
print(unpacked_data)
我想在 C 中创建类似于结构的东西,但在 Python 中。具体来说,我想这样:
typedef struct __attribute__((__packed__))
{
float x[4];
uint8 y;
int z;
} structName;
在 Python 中。我在某处读到我可以使用命名元组但想避免填充,但我不知道如何在 Python 中进行填充。谁能告诉我该怎么做?我会在UDP通信中使用它。
如果你想序列化(例如:保存到文件或通过网络发送),你应该检查 struct 库基本上你可以定义如何保存你的数据,多少字节和顺序。
您可以在 python 中使用 class 来表示您的结构,并添加两个函数以将其打包成较小的二进制数据,并在您再次需要时从中解压
你的例子应该是:
import struct
class StructName():
def __init__(self, xs=None, y=None, z=None):
self.xs = xs
self.y = y
self.z = z
def pack(self):
return struct.pack("!4fBi", *self.xs, self.y, self.z)
def unpack(self, packed_bytes):
*self.xs, self.y, self.z = struct.unpack("!4fBi", packed_bytes)
if __name__ == "__main__":
s = StructName([1.0, 0.5, 2.0, 0.], 255, 42)
tmp = StructName()
bytedata = s.pack()
print("s", s.xs, s.y, s.z) # s [1.0, 0.5, 2.0, 0.0] 255 42
print(len(bytedata), bytedata) # 21 b'\x00\x00\x80?\x00\x00\x00?\x00\x00\x00@\x00\x00\x00\x00\xff\x00\x00\x00*\x00\x00\x00'
tmp.unpack(bytedata) # fill data into tmp class
tmp.xs[0] = 42.5
print("tmp", tmp.xs, tmp.y, tmp.z) # tmp [42.5, 0.5, 2.0, 0.0] 255 42
pack
和 unpack
函数中的格式字符串是 "!4fBi" 其中:
- ! - 使用网络字节序 (bigendian)
- 4f - 四个浮点数(4*4 字节)
- B - 一个无符号字符(1 字节)
- i - 一个有符号整数(4 字节)
有关更多信息,请查看此部分:Format Characters
在已接受答案的评论部分回答评论
import re
import struct
def get_values_from_binary(format_str, bin_data):
val_regex = re.compile(r"[a-zA-Z]([0-9]+)?")
ls = struct.unpack(format_str, bin_data)
res = []
i = 0
for m in val_regex.finditer(format_str):
groups = m.groups()
current_length = 1
if groups is not None and groups[0] is not None:
current_length = int(groups[0])
res.append(ls[i:i + current_length])
i += current_length
return res
if __name__ == "__main__":
f_str = "<I7f7f7f3f4ffI"
data = [0]*7 + [0.3]*7 + [0.5]*7 + [0.9]*3 + [1.0]*4 + [2.5, 3.5, 1]
print(data)
bindata = struct.pack(f_str, *data)
unpacked_data = get_values_from_binary(f_str, bindata)
print(unpacked_data)