Problema al ejecutar las funciones de un archivo DLL utilizando ctypes en Python orientada a objetos

StackOverflow https://stackoverflow.com/questions/1170372

Pregunta

Por supuesto, espero que esto no será un problema ya ha respondido o un ser estúpida. Recientemente he estado programando con varios instrumentos. Tratando de comunicarse entre ellos con el fin de crear un programa de pruebas. Sin embargo he encoutered algunos problemas con un instrumento específico cuando estoy tratando de llamar a las funciones que he "enmascarados" desde el archivo DLL de instrumentos. Cuando utilizo el intérprete de Python interactiva que funciona perfectamente (aunque su gran cantidad de clobbering palabra). Pero cuando implemente las funciones de una manera orientada a objetos falla el programa, bueno, en realidad no falla simplemente no hace nada. Este es el primer método que se llama: (ctypes y ctypes.util se importa)

    def init_hardware(self):
    """ Inits the instrument """
    self.write_log("Initialising the automatic tuner")
    version_string = create_string_buffer(80)
    self.error_string = create_string_buffer(80)
    self.name = "Maury MT982EU"
    self.write_log("Tuner DLL path: %s", find_library('MLibTuners'))
    self.maury = WinDLL('MlibTuners')
    self.maury.get_tuner_driver_version(version_string)
    if (version_string.value == ""):
        self.write_log("IMPORTANT: Error obtaining the driver version")
    else:
        self.write_log("Version number of the DLL: %s" % version_string.value)
    self.ThreeTypeLong = c_long * 3

Ahora que las obras se hinchan, todo es perfecto y me sale perfecto log-entradas. Pero cuando trato de ejecutar un procedimiento adicional en el programa llamado:

def add_tuner_and_controller(self, name, serial_number, tuner_number=0):
    """ Adds the tuner to the driver object, controller is inside the tuner """
    self.write_log("Adding tuner %d and the built-in controller" % tuner_number)
    TempType = self.ThreeTypeLong()
    self.maury.add_controller(c_short(tuner_number), c_char_p(self.file_path), c_char_p(name), c_int(0), c_int(0), 
                              c_long(0), c_short(serial_number), self.error_string)
    self.maury.add_tuner(c_short(tuner_number), c_char_p(name), c_short(serial_number), c_short(0),
                            c_short(1), pointer(c_double()), TempType, pointer(c_double()), pointer(c_double()),
                            pointer(c_double()), self.error_string)

El programa deja de funcionar de repente / sigue funcionando, nada happenes cuando el -line "self.maury" se llama. Cuando coloco todo en el método init_hardware funciona perfectamente, así que supongo que hay una ligera memoria "error" o algo con la estructura orientada a objetivos. Realmente quiero que siga siendo de esta manera, hay alguna forma de aislar las funciones de esta forma? o tengo que limitarme a una gran parte del código?


EDIT:
Información de Documentación :
[Leyenda: Las estrellas indican los punteros y los paréntesis indican las matrices]

La función add_tuner añade o actualizaciones de un sintonizador en el objeto controlador de sintonizador.

short add_tuner(short tuner_number, char model[ ], short serial_number, short ctlr_num, short ctlr_port, short *no_of_motors, long max_range[ ], double *fmin, double *fmax, double *fcrossover, char error_string[ ])

salida : no_motors, max_range (array of three numbers), fmin, fmax, fcrossover,error_string (80+ characters long), function-return->Error flag



La función add_controller añade o actualizaciones de un controlador en el objeto conductor sintonizador

short add_controller(short controller_number, char driver[ ], char model[ ], int timeout, int address, long delay_ms, char error_string[ ])

salida : error_string, function-return->Error flag

¿Fue útil?

Solución 3

descubrí que la única manera de llamar a las funciones de la DLL exportado era utilizar la DLL a través de un parámetro en cada método. (El programa exporta el archivo DLL y en cada método llamado lo enviará como parámetro). Se ve bastante feo, pero esa es la única manera que encontré para estar trabajando para mí. Incluso he intentado exportar el archivo DLL como un atributo de clase. El sistema que estoy trabajando es bastante fuerte, así que supongo que hay algunos en algún lugar boboo-código que hace que falle. Gracias por todos los comentarios y consejos!

/ Mazdak

Otros consejos

No estoy seguro acerca de su problema exacto, pero aquí hay un par de consejos generales:

Para aquellas funciones que usted está llamando fuera del constructor, no te recomiendo configurando sus argtypes en el constructor también. Una vez que se ha declarado el argtypes, que no es necesario para emitir todos los argumentos como c_short, c_double, etc. Por otra parte, si accidentalmente se pasa un argumento incorrecto a una función C, Python lanzará un error de ejecución en lugar de chocar dentro la DLL.

Otro detalle menor, pero usted debe utilizar x = 0; byref(x) o tal vez POINTER (c_double)() en lugar de puntero (c_double ()) en el sintonizador y el controlador.

He estado escribiendo algunas clases ctypes en Python 2.6 recientemente también, y no he visto ningún problema como lo que describes. Desde allí, aparentemente, no son ningún informes de errores de Python en que, o bien, creo firmemente que sólo hay un detalle que estamos pasando por alto tanto en su método que está teniendo un problema.

¿Alguno de los parámetros en complemento del tratamiento o add-sintonizador de valores realmente volver?

recomendamos que defina prototipos de sus funciones, en lugar de llamar a ellos directamente con los moldes de todos los parámetros.

Estoy seguro de que ha leído esta página ya , pero la sección que desea mirar es prototipos de funciones. Hace que el código mucho más limpio y más fácil de rastrear / depuración.

También - como Mark Rushakoff menciona también - utilizando puntero (c_double ()) y al igual que en su llamada es bastante repulsivo. Tengo mucha mejor suerte w / puntero (), y recomiendo una vez más que el valor predeclara como una variable, y pasar la variable en su llamada a la función. Entonces, al menos se puede examinar su valor después de un comportamiento extraño.

EDIT: Por lo que su prototipo y la llamada se verá algo como esto:

prototype = WINFUNCTYPE(
    c_int,              # Return value (correct? Guess)
    c_short,            # tuner_number
    c_char_p,           # file_path
    c_char_p,           # name
    c_int,              # 0?
    c_int,              # 0?
    c_long,             # 0?
    c_short,            # serial_number
    c_char_p,           # error_string
)
# 1 input, 2 output, 4 input default to zero (I think; check doc page)
paramflags = (1, 'TunerNumber' ), (1, 'FilePath' ), (1, 'Name' ), ...
AddController = prototype(('add_controller', WinDLL.MlibTuners), paramflags)

A continuación, su llamada es mucho más limpio:

arg1 = 0
arg2 = 0
arg3 = 0
AddController(tuner_number, self.file_path, name, arg1, arg2, arg3, 
    serial_number, self.error_string)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top