Verständnisfrage zu ctypes/DLL/struct Teil II

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.
Benutzeravatar
Damaskus
Administrator
Beiträge: 909
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Montag 5. Mai 2008, 15:10

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
BlackJack

Montag 5. Mai 2008, 15:31

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.
Benutzeravatar
Damaskus
Administrator
Beiträge: 909
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Montag 5. Mai 2008, 16:34

Mein C Wissen ist sehr bescheiden :oops:
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.
BlackJack

Montag 5. Mai 2008, 21:52

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
Benutzeravatar
Damaskus
Administrator
Beiträge: 909
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Dienstag 6. Mai 2008, 09:57

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 :D

Gruß
Damaskus
Benutzeravatar
Damaskus
Administrator
Beiträge: 909
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Dienstag 13. Mai 2008, 11:57

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
BlackJack

Dienstag 13. Mai 2008, 12:53

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)
    ]
Benutzeravatar
Damaskus
Administrator
Beiträge: 909
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Dienstag 13. Mai 2008, 13:21

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
BlackJack

Dienstag 13. Mai 2008, 13:30

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``)
Benutzeravatar
Damaskus
Administrator
Beiträge: 909
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Dienstag 13. Mai 2008, 14:21

(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)
        ...
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Dienstag 13. Mai 2008, 14:27

Es müsste ``ctypes.c_char * 32`` sein.
Benutzeravatar
Damaskus
Administrator
Beiträge: 909
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Dienstag 13. Mai 2008, 14:39

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 :wink: :
class c_char
Represents the C char datatype, and interprets the value as a single character. The constructor accepts an optional string initializer...
Benutzeravatar
Damaskus
Administrator
Beiträge: 909
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Montag 19. Mai 2008, 15:19

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
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Montag 19. Mai 2008, 15:54

Sicher, dass ``transceiverType`` ein `c_uint` ist und kein `c_ushort`? Das würde es nämlich erklären.
Benutzeravatar
Damaskus
Administrator
Beiträge: 909
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Montag 19. Mai 2008, 18:26

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
Antworten