Problema che l'esecuzione di funzioni di una DLL file utilizzando ctypes orientata agli Oggetti Python

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

Domanda

Spero che questo non sia già risposto a una domanda o un uno stupido.Ultimamente ho cercato di programmazione con diversi strumenti.Cercando di comunicare tra di loro al fine di creare un programma di test.Tuttavia ho riscontrato alcuni problemi con uno strumento specifico, quando sto cercando di funzioni di chiamata che ho "mascherato" per strumenti di file DLL.Quando uso interattivo shell di python funziona perfettamente (anche se il suo un sacco di word sovrascrivere).Ma quando ho implementare le funzioni in un object-oriented modo il programma non riesce, beh, in realtà non manca semplicemente non fare nulla.Questo è il primo metodo che chiama:(ctypes e ctypes.util è importato)

    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

Ora che funziona onde, tutto è perfetto e io, un perfetto registro voci.Ma quando cerco di eseguire un ulteriore metodo, in un programma chiamato:

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)

Il programma smette improvvisamente di funzionare/continua a correre , nulla happenes quando il "self.maury"-linea è chiamata.Quando metto tutto in init_hardware metodo funziona perfettamente così sto indovinando che c'è un leggero errore "memoria" o qualcosa del genere con l'obiettivo struttura orientata.Davvero voglio restare in questo modo, esiste un modo per isolare le funzioni in questo modo?o devo limitare per me un grande pezzo di codice?


EDIT:
Documentazione info:
[Legenda:Le stelle indicano i puntatori e le parentesi indicano le matrici]

Il add_tuner funzione aggiunge o aggiorna un tuner tuner driver oggetto.

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[ ])

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



Il add_controller funzione aggiunge o aggiorna un controller driver del sintonizzatore oggetto

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

Uscita: error_string, function-return->Error flag

È stato utile?

Soluzione 3

Ho scoperto che l'unico modo per chiamare le funzioni della DLL esportate era quello di utilizzare DLL attraverso un parametro in ogni metodo.(il programma esporta il dll e in ogni metodo chiamato verrà inviato come parametro).Sembra abbastanza brutto, ma quello è l'unico modo che ho trovato per essere a lavorare per me.Ho anche provato l'esportazione di DLL come un attributo di classe.Il sistema su cui sto lavorando è abbastanza pesante quindi credo che c'è qualche boboo-il codice da qualche parte che la fa fallire.Grazie per tutti i suggerimenti e consigli!

/Mazdak

Altri suggerimenti

Io non sono sicuro circa il vostro problema esatto, ma ecco un paio di consigli generali:

Per quelle funzioni che si sta chiamando fuori del costruttore, raccomando caldamente di impostare i loro argtypes nel costruttore, come pure.Una volta che hai dichiarato argtypes, non c'è bisogno di gettare tutti gli argomenti c_short, c_double, etc.Inoltre, se si esegue accidentalmente passare un argomento non corretto per una funzione C, Python, verrà generato un errore di runtime invece di cadere all'interno della DLL.

Un altro piccolo dettaglio, ma si dovrebbe essere utilizzando x = 0; byref(x) o forse POINTER(c_double)() invece di puntatore(c_double()) il tuner e il controller.

Ho scritto alcuni ctypes classi in Python 2.6 e di recente, e non ho visto alcun problemi come quello che stai descrivendo.Dal momento che c'è a quanto pare non sono da Python bug report sull'che sia, credo fortemente che c'è solo un dettaglio che si sia vista nel metodo che sta avendo un problema.

Sono uno dei parametri aggiuntivi controller o add-tuner in realtà i valori di ritorno?

Consiglia di definire i prototipi delle funzioni, piuttosto che chiamare la loro diretta con calchi di tutti i parametri.

Sono sicuro che hai letto questa pagina già, ma la sezione che si desidera guardare è Prototipi di Funzione.Rende il codice molto più pulito e più semplice per tracciare/debug.

Anche -- Mark Rushakoff menziona anche-utilizzo del puntatore(c_double()) e come la vostra chiamata è abbastanza icky.Ho molta più fortuna w/ PUNTATORE(), e raccomandare ancora una volta che, predeclare il valore di una variabile, e passare la variabile nella chiamata alla funzione.Quindi almeno si può esaminare il suo valore dopo per il suo strano comportamento.

EDIT:Così il prototipo e la chiamata sarà simile a questa:

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)

Poi la chiamata è molto più "pulito":

arg1 = 0
arg2 = 0
arg3 = 0
AddController(tuner_number, self.file_path, name, arg1, arg2, arg3, 
    serial_number, self.error_string)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top