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)
精彩评论