2011-02-22 16 views
5

estoy usando ctypes y he definido a esta estructura con el fin de pasar parámetros¿Cómo creo una cadena de python a partir de una estructura ctype?

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

Entonces llamo a la función C usando el siguiente código, pero no sé cómo crear una cadena de la estructura que he creado.

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] 

Quiero crear una cadena de Python usando los primeros n bytes del buffer (el buffer contiene caracteres NULL pero tengo que manejar esta situación y crear la cadena con 0x00 caracteres/L Si es necesario). La asignación

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

no funciona porque bacause trunca la cadena si aparece 0x00. Cualquier idea es bienvenida. Gracias por adelantado.

+0

En Python 2.6.3, he probado la creación de una matriz ctypes como su búfer, pero no puedo ver que se trunca en realidad. De esta manera: ar = (ctypes.c_char * 10)(); ar.value = "prueba"; afirmar ar [: 6] == 'test \ x00 \ x00'. ¿Me estoy perdiendo de algo? – aknuds1

Respuesta

3

Su problema es que ctypes trata de hacer un poco de magia para usted con char matrices, auto-convertirlos en cadenas terminadas en nulo. Puede sortear esta magia utilizando el tipo ctypes.c_byte en lugar de ctypes.c_char y recuperando el valor como una cadena con ctypes.string_at. Puede hacer que el acceso al miembro un poco más agradable con una propiedad ayudante de la clase de estructura, tales como:

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

Creo que necesita enviar un puntero a una cadena C en su my_struct, y no una cadena C directamente, porque las cadenas C tienen terminación nula. Trate de hacerlo de esta manera:

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

Veo lo que estás tratando de hacer, pero eso no es correcto si la estructura esperada por la biblioteca con la que OP está interactuando tiene el buffer directamente integrado en la estructura. – llasram

Cuestiones relacionadas