所以我有两个简单的ctype结构
class S2 (ctypes.Structure):
_fields_ = [
('A2', ctypes.c_uint16*10),
('B2', ctypes.c_uint32*10),
('C2', ctypes.c_uint32*10) ]
class S1 (ctypes.Structure):
_fields_ = [
('A', ctypes.c_uint16),
('B', ctypes.c_uint32),
('C', S2) ]是否有可能这样做,例如,对名称?列表是如何用名称处理的?
编辑:
struc.pack使用
test_data = '0100000002000000' + 10*'01' + 10*'01' + 10*'01'
S2 = collections.namedtuple('S2', ['A2', 'B2', 'C2'])
S1 = collections.namedtuple('S1', ['A', 'B', 'REF_to_S2'])
Data2 = S2._make(struct.unpack('10p10p10p', binascii.unhexlify(test_data[16:])))
##this is not working, because there must be 3 args..
Data1 = S1._make(struct.unpack('ii', binascii.unhexlify(test_data[0:16])))最后,我希望以可读格式打印数据(具有键:值对可见)。但现在我不知道该如何处理两个不同名称的解包操作……?
这个unpack.struct操作将处理值类型问题,对吗?
发布于 2013-04-26 19:16:39
是否有可能这样做,例如,对名称?
这取决于你所说的“相同”是什么意思。您可以使用相同的字段轻松地创建namedtuple类型:
S2 = collections.namedtuple('S2', ['A2', 'B2', 'C2'])
S1 = collections.namedtuple('S1', ['A', 'B', 'C'])然而,他们显然不是相同的类型,不会有相同的行为。
首先,这些字段是一般的Python属性(也是普通的tuple成员),这意味着它们没有静态类型;它们可以保存任何类型的值。
所以,你可以这样做:
s2 = S2([ctypes.c_uint16(i) for i in range(10)],
[ctypes.c_uint32(i) for i in range(10)],
[ctypes.c_uint32(i) for i in range(10)])
s1 = S1(ctypes.c_uint16(1), ctypes.c_uint32(2), s2)但你也可以这样做:
s2 = S2('a', 'b', 'c')
s1 = S1('d', 'e', s2)…甚至:
s1 = S1('d', 'e', 'f')还要注意的是,即使是第一个示例也实际上创建了10个list值的ctypes,而不是ctypes数组。如果你想要的话,你必须显式地投出它们。
其次,namedtuples是tuples的扩展,这意味着它们是不可变的,所以您不能这样做:
s1.C = s2最重要的是,namedtuple不能用作ctypes.Structure-you不能将它传递给C函数,如果您想以某种特定的二进制格式序列化它,则必须编写手动逻辑(例如,围绕struct.pack),等等。
列表是如何用名称处理的?
如上所述,namedtuple的成员不是静态类型的,可以保存任何类型的值。因此,它们的处理方式与在tuple、list、普通类实例、全局变量等中的处理方式相同。只要在其中插入一个list,就可以得到一个list。
是的,stuct.pack是我所需要的。但我不知道该如何指出s1中的最后一个值是引用s2结构。
在namedtuple方面,您只需使用一个S2实例作为S1.C的值,如上面的示例所示。同样,namedtuple的项/属性与Python中的任何其他属性/变量/等等一样,只是保存对对象的引用的名称。因此,s1 = S1(1, 2, s2)将把s1的第三项转换为对s2引用的同一个对象的另一个引用。
至于如何使用struct来序列化数据:struct模块没有任何方法直接委托给嵌入式对象。但是,由于pack的输出只是一个bytes (或者在Python2.x中是str)对象,所以您可以通过正常的字符串操作来完成这个任务:
# version 1
s2_struct = struct.Struct('!HII')
s1_header = struct.Struct('!HI')
def pack_s2(s2):
return s2_struct.pack(s2.A2, s2.B2, s2.C2)
def unpack_s2(s2):
return S2._make(s2_struct.unpack(s2))
def pack_s1(s1):
return s1_header.pack(s1.A, s1.B) + pack_s2(s1.C)
def unpack_S1(s1):
offset = len(s1_header)
a, b = s1_header.unpack(s1[:offset])
c = unpack_s2(s1[offset:])
return S1._make(a, b, c)(我个人会使用S2(*struct.unpack而不是S2._make,但由于文档反复使用后者,我想这一定是…的预定方法)
或者,您可以手动平平格式字符串:
s2_struct = struct.Struct('!HII')
s1_struct = struct.Struct('!HIHII')
def pack_s2(s2):
return s2_struct.pack(s2.A2, s2.B2, s2.C2)
def pack_s1(s1):
return s1_struct.pack(s1.A, s1.B, s1.C.A2, s1.C.B2, s1.C.C2)
def unpack_s2(s2):
return S2._make(s2_struct.unpack(s2))
def unpack_S1(s1):
a, b, a2, b2, c2 = s1_struct.unpack(s1)
c = S2(a2, b2, c2)
return S1(a, b, c)我认为第二个版本更容易阅读,但也更容易出错,并要求您考虑在二进制级别而不是Python上组合对象,所以…选择两种罪恶中较小的一种。
https://stackoverflow.com/questions/16243160
复制相似问题