bigendianstrutu中的字符串

2024-09-30 05:24:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我想做些类似的事情:

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只能是本机字节顺序。但是也许还有其他方法可以让字符串的长度在字符串前面指定。我喜欢结构如何容易地从套接字读/写。以及如何定义字段,然后才能像这样使用它:

^{pr2}$

问题是:如何在bigendianstruction中创建可变长度字段?因为Python不允许我使用c_char_p.Script根本无法运行。这是错误:

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'>

Tags: inpyfieldspacketlinectypeslengthclass
1条回答
网友
1楼 · 发布于 2024-09-30 05:24:25

此类型:

class PacketString(BigEndianStructure):
    _fields_ = [("length", c_ushort),
                ("value", c_char_p)]

…不像你想的那样,甚至忽略了结尾问题。它是一个结构,它包含一个ushort长度,然后一个指向内存中其他地方的实际字符串数据的指针。在

换句话说,它就像这个C结构:

^{pr2}$

您需要的是一个以长度为前缀的字符串,该字符串直接内嵌在结构内部。为此,C结构是:

struct PacketString {
    unsigned short length;
    char value[1];
};

这就是所谓的“结构黑客”。这实际上不是合法的C,但它恰好与每个已知的C89编译器和大多数C99和C++编译器一起工作。有关详细信息,请参见C FAQ entry。在

那么,你能在ctypes中做同样的事情吗?嗯,是的,但没那么有用:

class PacketString(BigEndianStructure):
    _fields_ = [("length", c_ushort),
                ("value", c_char * 0)]

这可能会变得复杂;有关详细信息,请参见文档中的Variable-sized data types。尤其是,您不能在p.value上调用resize;您需要计算p自身的大小,然后将p._fields_[1]的类型更改为have the right type,然后

好吧,这就是为什么医生说:

Another way to use variable-sized data types with ctypes is to use the dynamic nature of Python, and (re-)define the data type after the required size is already known, on a case by case basis.

换句话说:

class LocalPacketString(BigEndianStructure):
    _fields_ = [("length", c_ushort),
                ("value", c_char * length)]
ps = LocalPacketString(length, buff)

但是,您可能会注意到,这并没有真正节省您的工作,而只是保持类型分离。在


总之,struct hack甚至不是有效的C,而且它不能很好地映射到ctypesctypes.Structure不是表示可变长度前缀字符串的好方法。在

相关问题 更多 >

    热门问题