开发者

How do I build a python string from a ctype struct?

I'm using ctypes and I've defined this struct in order to pass parameters

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

Then I call the C function using the following code, but I don't know how to create a string from the struct I've created.

class Cli开发者_如何学JAVAent():

    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]

I want to create a python string using the first n bytes of the buffer (the buffer contains NULL characters but I have to handle this situation and create the string with /0x00 characters if necesary). The asignation

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

is not working bacause truncates the string if 0x00 appears. Any idea is welcome. Thanks in advance.


Your problem is that ctypes tries to do some magic for you with char arrays, auto-converting them into NUL-terminated strings. You can get around this magic by using the ctypes.c_byte type instead of ctypes.c_char and retrieving the value as a string with ctypes.string_at. You can make accessing the member a little nicer with a helper property on the structure class, such as:

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", " ")


I think you need to send a pointer to a C string in your my_struct, and not a C string directly, because C strings are null-terminated. Try to do it like this:

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)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜