variablendeklaration für externe hardware

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mmuser
User
Beiträge: 7
Registriert: Montag 11. Februar 2008, 14:16

hallo,
ich (python-newbie) möchte eine externe hardware über python ansprechen. via ctypes() habe ich die dll des geräts eingebunden, entsprechende teilefolge lassen erahnen, dass die kommunikation mit der hardware (oder zumindest der dll) funktioniert.
ich möchte jetzt einen befehl ausführen, der in der SDK-Dokumentation des geräts beschrieben ist. mit dem befehl muss ich einen parameter übergeben. laut dokumentation ist dieser parameter vom typ ZebDevice* (description: Pointer to device, size: 4 byte). wie kann ich jetzt einen solchen pointer erstellen? soweit ich weiß, muss man doch in python nicth deklarieren.
muss ich dafür eine klasse ZebDevice* erstellen?
vg, mario.
BlackJack

Wenn Du von Python aus auf Felder von so einem `ZebDevice` zugreifen willst/musst, dann müsstest Du die Struktur mit `ctypes`-Objekten nachbauen. Wenn das nur ein Pointer ist, den man bei der API herum reicht, geht auch ein `ctypes.c_void_p`.
mmuser
User
Beiträge: 7
Registriert: Montag 11. Februar 2008, 14:16

ich versteh nur die hälfte, aber klingt so als könnte es funktionieren:) ist dieses c_void_p eine methode von ctypes? oder wo ist das dokumentiert?
BlackJack

Das ist eine Klasse die den C-Datentyp `void*` modelliert. Die Klasse kann man verwenden, wo `ctypes` "C-Typen" erwartet, und Instanzen davon wo `void*` als Werte erwartet werden.

Dokumentation gibt's da wo die Standardbibliothek halt dokumentiert ist: http://docs.python.org/lib/module-ctypes.html
mmuser
User
Beiträge: 7
Registriert: Montag 11. Februar 2008, 14:16

also ich habs jetzt mal mit

Code: Alles auswählen

dev=ctypes.c_void_p()
versucht. wenn ich dann den befehl aufrufe (ctypes.windll.zebsdk.ZebDeviceManager_GetDevice(dev)) bekomme ich eine Access violation exception. mit admin rechten kann das aber nicths zu tun haben (habe die konsole als admin gestartet)...
BlackJack

Damit hast Du einen Null-Pointer erstellt. Das entspricht in C etwa:

Code: Alles auswählen

void *dev = NULL;
ZebDeviceManager_GetDevice(dev);
Die Funktion will also einen Pointer auf eine `ZebDevice`-Struktur um diese mit Daten zu füllen. Da kann man dann nicht einfach einen NULL-Pointer, also einen "Pointer auf nichts", übergeben. Die Funktion versucht damit an Adresse 0 etwas zu schreiben was zu einem Speicherzugriffsfehler führt.

Also musst Du die Struktur in `ctypes`-Objekten nach bauen, eine Instanz erstellen und einen Pointer darauf übergeben.
mmuser
User
Beiträge: 7
Registriert: Montag 11. Februar 2008, 14:16

hmm, aber woher weiß ich was ich da "bauen" soll`? in der sdk-dokumentation gibt es etwas beispielcode. da steht "typedef struct {} ZebDevice;" weiß nicth welche sprache das sein soll aber sieht nicth so aus als gäbe es für das device irgendwelche methoden oder attribute...
BlackJack

Das sieht nach C aus. Also wird es auch irgend wo Header-Dateien geben, wo diese Struktur deklariert ist. Wenn ``ZebDeviceManager_GetDevice()`` wirklich einen Pointer auf so eine Struktur haben will, muss man mehr haben als eine leere Struktur als Deklaration oder es muss einen anderen Weg geben einen Pointer auf so eine Struktur von der DLL zu bekommen.
mmuser
User
Beiträge: 7
Registriert: Montag 11. Februar 2008, 14:16

naja, in der documentation steht, 'a handle to the [...] device must be retrieved from the SDK. Procedure: ZebDeviceManager_GetDevice(ZebDevice** device);'
also die wollen damit sagen diese methode gibt das device zurück, aber irgendwie muss man doch auch ein device als parameter übergeben.
bei der beschreibung des befehls ..._GetDevice(ZebDevice** device) steht "device: pointer to a pointer which receives the device handle." ich verstehe das nicht. dann müsste es doch auch eine methode geben, um den 'pointer to a pointer' zu bekommen?
mmuser
User
Beiträge: 7
Registriert: Montag 11. Februar 2008, 14:16

ich habe von python aus ein setup fenster gestartet bekommen. ein setup fenster für das gerät. "to setup the parameters of the selected device click 'setup''. ich kann leider kein device auswählen, weil an den rechner keins angeschlossen ist (nur SDK installiert). ich werde das mal ausprobieren an dem rechner an dem das gerät angeschlossen ist, und melde mich dann in einiger zeit wieder.
vielen dank für die bisherige hilfe schonmal!
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Probier mal folgendes:

Code: Alles auswählen

import ctypes
dev=ctypes.c_void_p()
ZebDeviceManager_GetDevice(ctypes.byref(dev))
Da ja steht ein Pointer auf einen Pointer will die Funktion wahrscheinlich ein solches Struct erstellen und den Pointer darauf in dev schreiben.

Gruss
mmuser
User
Beiträge: 7
Registriert: Montag 11. Februar 2008, 14:16

import ctypes
dev=ctypes.c_void_p()
ZebDeviceManager_GetDevice(ctypes.byref(dev))
wow! das funktioniert! zumindest teilweise. es gibt keine fehlermeldung mehr. die antwort ist eher schlicht: 0
wenn der ..._GetDevice()-aufruf eine 0 zurückgibt, heisst das, dass ein fehler vorliegt. die ..._GetLastError() funktion gibt ein "Device '' not found, please execute the hardware setup" zurück. d.h. jetzt muss ich wirklich das gerät anschliessen und das setup ausführen.
vielen dank!
[was hab ich denn da gemacth? byref(dev) ist ein pointer auf die leere klasse dev??]
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Nein du übergibts dev einfach als Referenz (byref = by reference), d.h. wenn die Funktion selbst dev ändert, verändert sich auch dein dev, da es der gleiche Pointer ist.

Eingentlich erstellt das einen Pointer auf dev und da dev ein void-Pointer ist übergibst du einen Pointer auf einen Pointer auf eine beliebige Sache (hier das Struct).

Gruss
Antworten