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