Problème fonctions en cours d'exécution à partir d'un fichier DLL à l'aide ctypes en Python orientée objet

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

Question

J'espère que ce ne sera pas une question déjà répondu ou stupide. Récemment, j'ai été la programmation avec plusieurs instruments. Essayer de communiquer entre eux afin de créer un programme de test. Cependant, j'ai encoutered quelques problèmes avec un instrument spécifique quand je suis en train d'appeler des fonctions que je suis « masqué » à partir du fichier DLL instruments. Lorsque j'utilise le shell Python interactif, il fonctionne parfaitement (bien que beaucoup de son mot clobbering). Mais quand j'implémenter les fonctions d'une manière orientée objet le programme échoue, bien en fait, il ne manque pas ça ne fait rien. Ceci est la première méthode qui est appelée: (est importé ctypes et ctypes.util)

    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

Maintenant que les travaux se gonflent, tout est parfait et je reçois log-entrées parfaites. Mais quand je tente d'exécuter une autre méthode dans le programme appelé:

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)

Le programme arrête soudain / continue à courir, rien happenes lorsque le « self.maury » -ligne est appelé. Quand je mets tout dans la méthode init_hardware cela fonctionne parfaitement si je devine qu'il ya une légère mémoire « erreur » ou quelque chose avec la structure orientée objectif. Je veux vraiment qu'il reste de cette façon, est de toute façon d'isoler les fonctions de cette manière? ou dois-je me limiter à un gros morceau de code?


EDIT: info Documentation :
[Légende: Les étoiles indiquent les pointeurs et les tableaux entre parenthèses indiquent]

La fonction add_tuner ajoute ou met à jour un tuner dans l'objet pilote tuner.

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

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



La fonction add_controller ajoute ou met à jour un contrôleur dans l'objet pilote tuner

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

Sortie : error_string, function-return->Error flag

Était-ce utile?

La solution 3

Je trouve que la seule façon d'appeler les fonctions dans la DLL exportée était d'utiliser la DLL par un paramètre dans chaque méthode. (Le programme exporte le dll et dans chaque méthode appelée il envoie comme paramètre). Il semble assez laid, mais c'est la seule manière que je trouvais à travailler pour moi. J'ai même essayé d'exporter le DLL comme un attribut de classe. Le système que je travaille avec est assez costaud, je pense que oui il y a quelque part une boboo-code qui fait échouer. Merci pour tous les commentaires et conseils!

/ Mazdak

Autres conseils

Je ne suis pas sûr de votre problème exact, mais voici deux ou trois conseils généraux:

Pour les fonctions que vous appelez en dehors du constructeur, je recommande fortement la mise en leur argtypes dans le constructeur ainsi. Une fois que vous avez déclaré le argtypes, vous ne devriez pas avoir de jeter tous les arguments comme c_short, c_double, etc. De plus, si vous ne passez accidentellement un argument incorrect à une fonction C, Python déclenche une erreur d'exécution au lieu de se briser à l'intérieur la DLL.

Un autre détail mineur, mais vous devez utiliser x = 0; byref(x) ou peut-être POINTER (c_double)() au lieu de pointeur (c_double ()) dans le syntoniseur et le contrôleur.

J'ai écrit quelques classes ctypes en Python 2.6 récemment aussi bien, et je ne l'ai pas vu de problèmes comme ce que vous décrivez. Comme il n'y a apparemment pas de rapports de bogues de Python sur ce soit, je crois fermement qu'il ya juste un détail minutieux que nous sommes tous les deux négligeons dans votre méthode qui a un problème.

Y at-des paramètres dans add-contrôleur ou add-tuner retour en fait des valeurs?

vous recommandons fortement de définir des prototypes de vos fonctions, au lieu de les diriger avec des moulages de tous les paramètres.

Je suis sûr que vous avez lu cette page déjà, mais la section vous voulez regarder est fonction prototypes. Rend le code plus propre et plus facile à tracer / debug.

En outre - comme Mark Rushakoff mentionne aussi - pointeur à l'aide (c_double ()) et comme dans votre appel est assez dégueu. J'ai beaucoup plus de chance w / POINTEUR (), et recommande encore une fois que vous prédéclarer la valeur comme une variable, et passer la variable dans votre appel de fonction. Ensuite, au moins vous pouvez examiner ensuite sa valeur pour un comportement étrange.

EDIT: Donc, votre prototype et appel ressemblera à quelque chose comme ceci:

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)

Ensuite, votre appel est beaucoup plus propre:

arg1 = 0
arg2 = 0
arg3 = 0
AddController(tuner_number, self.file_path, name, arg1, arg2, arg3, 
    serial_number, self.error_string)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top