Seite 1 von 1
Verständnisfrage zu ctypes/DLL/struct Teil II
Verfasst: Montag 5. Mai 2008, 15:10
von Damaskus
Fortsetzung zu
http://www.python-forum.de/topic-14459.html
Hallo Blackjack,
irgendwie scheitere ich noch immer an dem ganzen. Liegt aber wohl eher daran dass ich das gesamte Zusammenspiel von Pointern / Strukturen und ctypes noch nicht ganz verstehe.
Gibts dazu noch irgendwelche "leichte Kost" außer dem Python Manual?
Entweder bekomme ich als Rückmeldung eine SUCCESS und gleichzeitig eine Lesefehler auf Byte 0x000000 (was auch verständlich ist) oder ich bekomme je nachdem wie ich die Funktion aufrufe "ValueError: Procedure probably called with too many arguments (116 bytes in excess)"
Wäre toll wenn du mir noch einige Hinweise und Tipps hättest.
Hier mein bisheriges Script:
http://paste.pocoo.org/show/47502/
Danke!
Gruß
Damaskus
Verfasst: Montag 5. Mai 2008, 15:31
von BlackJack
Nach der Signatur im Vorgängerthread erwartet `xlGetDriverConfig` einen *Zeiger* auf eine `XLdriverConfig`-Struktur, der ist je nach Architektur 4 oder 8 Bytes gross. Du übergibst aber die Struktur als Wert, das sind ein paar Bytes zu viel.
Wie sieht's denn mit Deinem C-Wissen aus? Das Sternchen gehört zum Typ und nicht zum Namen und bedeutet "Zeiger". In `struct_xlGetApplConfig` sind auch ein paar Namen mit Sternchen, die eigentlich in die Typangabe gehören. Das könnte zwar zufällig so funktionieren, aber es ist nicht garantiert, dass ``int`` und ``int*`` die gleiche Anzahl von Bytes belegen.
Verfasst: Montag 5. Mai 2008, 16:34
von Damaskus
Mein C Wissen ist sehr bescheiden
Und mit dem Projekt versuch ich mich gleichzeitig in C und in ctypes etwas einzuarbeiten. Wobei ich inzwischen schon gemerkt habe dass ich mich evtl. etwas damit übernommen hab.
Aber interresieren tuts mich trotzdem und deshalb versuch ich weiterhin das ganze zu lernen. Auch wenns warscheinlich am C Grundwissen scheitert.
Das Sternchen gehört zum Typ und nicht zum Namen und bedeutet "Zeiger". In `struct_xlGetApplConfig` sind auch ein paar Namen mit Sternchen, die eigentlich in die Typangabe gehören.
Ok, wenn ich das richtig verstanden habe dann muss ich das Struct als Zeiger (Pointer) übergeben. Richtig?
Also z.B.
Code: Alles auswählen
# Treiber Konfig
#s = struct_xlGetDriverConfig()
s = pointer(struct_xlGetDriverConfig())
XLstatus = dll.xlGetDriverConfig(s)
print c_char_p(dll.xlGetErrorString(c_int(XLstatus))).value
Und in dem Struct selber auch noch Pointer definieren. An den geforderten Stellen halt.
Verfasst: Montag 5. Mai 2008, 21:52
von BlackJack
Sofern Du auf die Struktur von Python aus zugreifen möchtest oder musst, würde ich ein Exemplar von der Struktur an `s` binden und nur für die Übergabe an die DLL-Funktion einen Zeiger mit `byref()` erzeugen. Sonst hast Du beim Zugriff auf `s` ja immer die Indirektion über den Zeiger.
Code: Alles auswählen
# Treiber Konfig
s = struct_xlGetDriverConfig()
XLstatus = dll.xlGetDriverConfig(byref(s))
print c_char_p(dll.xlGetErrorString(c_int(XLstatus))).value
Verfasst: Dienstag 6. Mai 2008, 09:57
von Damaskus
Moin,
jetzt hats geklappt!
Lag nicht daran dass ich einen falschen Aufruf hatte sondern im Struct hatte ich einen Fehler.
Und ich hab die ganze Zeit im Prinzip den Fehler an der falschen Stelle, nämlich dem Aufruf der Funktion gesucht.
Danke für die Hilfe und die Geduld
Gruß
Damaskus
Verfasst: Dienstag 13. Mai 2008, 11:57
von Damaskus
Ich muss den Thread hier doch nochmal beleben...
Folgendes Problem gibts noch immer mit der Funktion.
Wenn ich die Funktion xlGetDriverConfig aufrufe läuft diese auch sauber durch und liefert "Success". Allerdings werden alle Felder ab dem "channel" Array nicht richtig gefüllt. Vor dem Aufruf enthalten die Felder None und nach dem Aufruf enthalten alle Felder 0 und nicht die gewünschten Werte.
Wenn ich den selben Aufruf in C mache wird das Struct korrekt befüllt.
Gibts da noch irgendwas zu beachten?
Gruß
Damaskus
Verfasst: Dienstag 13. Mai 2008, 12:53
von BlackJack
Zumindest hier
http://paste.pocoo.org/show/47502/ stimmt `struct_xlGetDriverConfig` nicht mit dem ``struct`` aus
http://www.python-forum.de/post-97401.html#97401 überein.
'reserved' und 'channels' sind Arrays, das müsste also so aussehen:
Code: Alles auswählen
class struct_xlGetDriverConfig(Structure):
_fields_ = [
("dllVersion", c_uint),
("channelCount", c_uint),
("reserved", c_uint * 10),
("channel", struct_XLchannelConfig * XL_CONFIG_MAX_CHANNELS)
]
Verfasst: Dienstag 13. Mai 2008, 13:21
von Damaskus
Das hab ich alles beachtet.
Ohne die Arrays läuft der Aufruf sowieso nicht fehlerfrei durch.
hier die Structs:
http://paste.pocoo.org/show/49740/
Und hier das Programm dazu:
http://paste.pocoo.org/show/49741/
Eigentlich müssten so alle Werte gefüllt werden. Bei anderen Funktionsaufrufen funktioniert es auch. Allerdings hat von denen keines eine SubStruktur.
Gruß
Damaskus
Verfasst: Dienstag 13. Mai 2008, 13:30
von BlackJack
In `struct_XLchannelConfig` gleich das erste Feld hat den falschen Typ. Du hast da ein Array von 32 *Zeigern* auf Zeichen deklariert, was im Original ein Array von 32 *Zeichen* ist. (Vorausgesetzt ``XL_MAX_LENGTH + 1 == 32``)
Verfasst: Dienstag 13. Mai 2008, 14:21
von Damaskus
(XL_MAX_LENGHT + 1) == 32 Stimmt!
Du meinst ich hab ein Array mit 32 Einträgen erstellt und ich brauch eins mit einem Eintrag der 32 Zeichen lang ist. Richtig?
Wenn das so richtig ist wie erstelle ich dann eines mit 32 Zeichen?
Ich hätte das dann so gemacht, was aber auch nicht richtig ist.
Code: Alles auswählen
name = c_char_p
name(32)
class struct_XLchannelConfig(Structure):
_fields_ = [
("name", name)
...
Verfasst: Dienstag 13. Mai 2008, 14:27
von Trundle
Es müsste ``ctypes.c_char * 32`` sein.
Verfasst: Dienstag 13. Mai 2008, 14:39
von Damaskus
Trundle hat geschrieben:Es müsste ``ctypes.c_char * 32`` sein.
Danke!
Genau das wars! Jetzt werden alle Felder richtig gefüllt.
Gruß
Damaskus
EDIT:
Wer lesen kann ist im Vorteil

:
class c_char
Represents the C char datatype, and interprets the value as a single character. The constructor accepts an optional string initializer...
Verfasst: Montag 19. Mai 2008, 15:19
von Damaskus
Und nochmal ne Frage zu dem ganzen Thema.
Wenn ich c_uint Werte aus dem Struct auslese bekomme ich unter C++ den Wert "02" und unter Python den Wert "2". Allerdings steht dann im nächsten Feld unter C++ z.B. der Wert "16" drinn und unter Python hat das nächste Feld den Wert "0" und erst das übernächste Feld den Wert "16".
Code: Alles auswählen
- hwtype --> 15 -
- hwindex --> 00 -
- hwchannel --> 00 -
- transceiverType --> 01 -
- transceiverState --> 16 -
- channelIndex --> 00 -
Code: Alles auswählen
hwtype 15
hwindex 0
hwchannel 0
transceiverType 1
transceiverState 0
channelIndex 16
Hat dazu noch jemand eine Idee bzw. einen Tip?
Gruß
Damaskus
Verfasst: Montag 19. Mai 2008, 15:54
von Trundle
Sicher, dass ``transceiverType`` ein `c_uint` ist und kein `c_ushort`? Das würde es nämlich erklären.
Verfasst: Montag 19. Mai 2008, 18:26
von Damaskus
Laut API ist es c_uint!
Allerdings hab ich mehrere solcher "Fehler" schon gehabt und deshalb ist es gut möglich. Werd ich morgen im Büro mal ausprobieren.
Danke!
Gruß
Damaskus
Verfasst: Montag 19. Mai 2008, 18:44
von Trundle
Naja, beim
Thread Teil I hast du
unsigned short transceiverType;
geschrieben.
Verfasst: Freitag 23. Mai 2008, 09:46
von Damaskus
Trundle hat geschrieben:Naja, beim
Thread Teil I hast du
unsigned short transceiverType;
geschrieben.
Stimmt! Hab ich vor lauter ausprobieren gar nciht mehr gesehen.
Wobei ich festgestellt hab dass es oftmals egal ist ob es uint, ubyte oder sonstwas ist. Zumindest bei der DLL.
Ist das eigentlich Normal?
Gruß
Damaskus
Verfasst: Freitag 23. Mai 2008, 13:55
von BlackJack
Nein das würde ich nicht als Normal bezeichnen. Du legst damit ja das Speicherlayout fest. Es kann höchstens sein, dass Du immer soviel unverschämtes Glück hattest, dass die Ausrichtung auf Wortgrenzen und die geschickte Kombination von zu grossen und zu kleinen Typen Deine Fehler teilweise wieder ausgeglichen haben. Das ist aber schon ziemlich unwahrscheinlich.