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
Verständnisfrage zu ctypes/DLL/struct Teil II
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.
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.
- Damaskus
- Administrator
- Beiträge: 995
- Registriert: Sonntag 6. März 2005, 20:08
- Wohnort: Schwabenländle
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.
Also z.B.
Und in dem Struct selber auch noch Pointer definieren. An den geforderten Stellen halt.
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.
Ok, wenn ich das richtig verstanden habe dann muss ich das Struct als Zeiger (Pointer) übergeben. Richtig?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.
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
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
- Damaskus
- Administrator
- Beiträge: 995
- Registriert: Sonntag 6. März 2005, 20:08
- Wohnort: Schwabenländle
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
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
- Damaskus
- Administrator
- Beiträge: 995
- Registriert: Sonntag 6. März 2005, 20:08
- Wohnort: Schwabenländle
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
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
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:
'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)
]
- Damaskus
- Administrator
- Beiträge: 995
- Registriert: Sonntag 6. März 2005, 20:08
- Wohnort: Schwabenländle
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
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
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``)
- Damaskus
- Administrator
- Beiträge: 995
- Registriert: Sonntag 6. März 2005, 20:08
- Wohnort: Schwabenländle
(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.
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)
...
- Damaskus
- Administrator
- Beiträge: 995
- Registriert: Sonntag 6. März 2005, 20:08
- Wohnort: Schwabenländle
Danke!Trundle hat geschrieben:Es müsste ``ctypes.c_char * 32`` sein.
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...
- Damaskus
- Administrator
- Beiträge: 995
- Registriert: Sonntag 6. März 2005, 20:08
- Wohnort: Schwabenländle
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".
Hat dazu noch jemand eine Idee bzw. einen Tip?
Gruß
Damaskus
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
Gruß
Damaskus
Naja, beim Thread Teil I hast du
geschrieben.unsigned short transceiverType;
- Damaskus
- Administrator
- Beiträge: 995
- Registriert: Sonntag 6. März 2005, 20:08
- Wohnort: Schwabenländle
Stimmt! Hab ich vor lauter ausprobieren gar nciht mehr gesehen.Trundle hat geschrieben:Naja, beim Thread Teil I hast dugeschrieben.unsigned short transceiverType;
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
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.