bob*_*bby 0 python ctypes endianness
我想做这样的事情:
from ctypes import *
class Packet(BigEndianStructure):
    _fields_ = [("length", c_ushort),
                ("session", c_uint),
                ("command", c_ushort)]
class PacketString(BigEndianStructure):
    _fields_ = [("length", c_ushort),
                ("value", c_char_p)]
class InitialPacket(Packet):
    _fields_ = [("time", PacketString)]
但是我收到错误,因为 c_char_p 只能采用本机字节顺序。但也许还有其他方法可以制作长度在它们之前指定的字符串。我只是喜欢结构如何轻松地从套接字读取/写入。以及如何定义 _fields_ 然后可以像这样使用它:
initialPacket = InitialPacket()
initialPacket.command = 128
问题是:如何在 BigEndianStructure 中创建可变长度字段?因为Python不允许我使用c_char_p。脚本根本不会运行。这是错误:
Traceback (most recent call last):
  File "C:\PKOEmu\test.py", line 8, in <module>
    class PacketString(BigEndianStructure):
  File "C:\Python27\lib\ctypes\_endian.py", line 34, in __setattr__
    fields.append((name, _other_endian(typ)) + rest)
  File "C:\Python27\lib\ctypes\_endian.py", line 24, in _other_endian
    raise TypeError("This type does not support other endian: %s" % typ)
TypeError: This type does not support other endian: <class 'ctypes.c_char_p'>
这个类型:
\n\nclass PacketString(BigEndianStructure):\n    _fields_ = [("length", c_ushort),\n                ("value", c_char_p)]\n\xe2\x80\xa6\xc2\xa0doesn\ 不会做你认为它会做的事情,甚至忽略字节序问题。它是一个包含 ushort 长度的结构,然后是指向内存中其他位置的实际字符串数据的指针。
\n\n换句话说,它就像这样的 C 结构:
\n\nstruct PacketString {\n    unsigned short length;\n    char *value;\n};\n您正在寻找的是一个长度前缀的字符串,其中该字符串直接内联在结构内部。为此,C 结构是:
\n\nstruct PacketString {\n    unsigned short length;\n    char value[1];\n};\n这称为“结构黑客”。这实际上不是合法的 C,但它恰好适用于每个已知的 C89 编译器以及大多数 C99 和 C++ 编译器。有关详细信息,请参阅C FAQ 条目。
\n\n那么,你能在 中做同样的事情ctypes吗?嗯,是的,但它没那么有用:
class PacketString(BigEndianStructure):\n    _fields_ = [("length", c_ushort),\n                ("value", c_char * 0)]\n这可能会变得复杂;有关详细信息,请参阅文档中的可变大小数据类型。特别是,您不能resize调用p.value; 你需要计算自己调整多少大小p,然后将类型更改p._fields_[1]为正确的类型,然后\xe2\x80\xa6
好吧,这就是为什么文档说:
\n\n\n\n\n将可变大小数据类型与 ctypes 结合使用的另一种方法是利用 Python 的动态特性,并在已知所需大小后根据具体情况(重新)定义数据类型。
\n
换句话说:
\n\nclass LocalPacketString(BigEndianStructure):\n    _fields_ = [("length", c_ushort),\n                ("value", c_char * length)]\nps = LocalPacketString(length, buff)\n但是,您可能会注意到,与仅保持类型分离相比,这并没有真正为您节省很多工作。
\n\n总之,struct hack 甚至不是有效的 C,并且它不能很好地映射到ctypes. Actypes.Structure不是表示可变长度长度前缀字符串的好方法。
| 归档时间: | 
 | 
| 查看次数: | 1296 次 | 
| 最近记录: |