【问题标题】:How do I build a python string from a ctype struct?如何从 ctype 结构构建 python 字符串?
【发布时间】:2011-07-02 06:00:48
【问题描述】:

我正在使用 ctypes,我已经定义了这个结构来传递参数

class my_struct(ctypes.Structure):
    _fields_ = [ ("buffer", ctypes.c_char * BUFSIZE),
                 ("size", ctypes.c_int )]

然后我使用以下代码调用 C 函数,但我不知道如何从我创建的结构中创建字符串。

class Client():

    def __init__(self):
        self.__proto = my_struct()
        self.client = ctypes.cdll.LoadLibrary(r"I:\bin\client.dll")

    def version(self):
        ret = self.client.execute(ctypes.byref(self.__proto))
        my_string = self.__proto.buffer[:self.__proto.size]

我想使用缓冲区的前 n 个字节创建一个 python 字符串(缓冲区包含 NULL 字符,但我必须处理这种情况并在必要时使用 /0x00 字符创建字符串)。委托

my_string = self.__proto.buffer[:self.__proto.size]

不工作,因为如果出现 0x00 会截断字符串。欢迎任何想法。提前致谢。

【问题讨论】:

  • 在 Python 2.6.3 中,我已经测试过创建一个像缓冲区一样的 ctypes 数组,但我看不到它实际上被截断了。像这样: ar = (ctypes.c_char*10)(); ar.value = "测试";断言 ar[:6] == 'test\x00\x00'。我错过了什么吗?

标签: python c string ctypes


【解决方案1】:

您的问题是ctypes 尝试使用char 数组为您做一些魔术,将它们自动转换为以NUL 结尾的字符串。您可以通过使用ctypes.c_byte 类型而不是ctypes.c_char 并使用ctypes.string_at 将值作为字符串检索来绕过这个魔法。您可以使用结构类上的辅助属性更好地访问成员,例如:

import ctypes
BUFSIZE = 1024

class my_struct(ctypes.Structure):
    _fields_ = [ ("_buffer", ctypes.c_byte * BUFSIZE),
                 ("size", ctypes.c_int )]

    def buffer():
        def fget(self):
            return ctypes.string_at(self._buffer, self.size)
        def fset(self, value):
            size = len(value)
            if size > BUFSIZE:
                raise ValueError("value %s too large for buffer",
                                 repr(value))
            self.size = size
            ctypes.memmove(self._buffer, value, size)
        return property(fget, fset)
    buffer = buffer()

proto = my_struct()
proto.buffer = "here\0are\0some\0NULs"
print proto.buffer.replace("\0", " ")

【讨论】:

    【解决方案2】:

    我认为您需要在 my_struct 中发送指向 C 字符串的指针,而不是直接发送 C 字符串,因为 C 字符串是以空值结尾的。尝试这样做:

    import ctypes
    
    BUFSIZE = 10
    
    class my_struct(ctypes.Structure):
        _fields_ = [ ("buffer", ctypes.POINTER(ctypes.c_char)),
                     ("size", ctypes.c_int )]
    
    cstr = (ctypes.c_char * BUFSIZE)()
    proto = my_struct(cstr)
    

    【讨论】:

    • 我明白你在做什么,但如果 OP 与之交互的库所期望的结构将缓冲区直接嵌入到结构中,那么这是不正确的。
    猜你喜欢
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多