Seite 1 von 2
[ctypes] Pointer auf Struktur als Argument
Verfasst: Mittwoch 18. März 2009, 18:19
von Jaspar
Hallo Community,
ich habe eine Frage zur korrekten Adaption einer C-Struktur, sowie dem entsprechenden Funktionsaufruf der API-Funktion.
Die Datenstruktur in C sieht folgendermaßen aus:
Code: Alles auswählen
typedef struct{
unsigned short dasChan
float* temp
} tcMuxRead
Es gibt nun eine API-Funktion welche einen Pointer auf obige Struktur als Argument übergeben bekommt.
Meine bisherige Adaption der C-Struktur in Python sieht folgendermaßen aus:
Code: Alles auswählen
class TCMUXREAD(ctypes.Structure):
_fields_ = [("dasChan", ctypes.c_ushort),
("temp", ctypes.c_float * 1)]
Ich erzeuge eine Instanz der Klasse TCMUXREAD indem ich folgendes schreibe:
Wenn ich nun aber die API-Funktion aufrufe und die Klassen-Instanz mittels ctypes.byref(tcMuxRead) übergebe bekomme ich einen AccessViolation-Fehler.
Ich bin für jede Hilfe dankbar.
Liebe Grüße,
Jas
Verfasst: Mittwoch 18. März 2009, 18:51
von rayo
Code: Alles auswählen
class TCMUXREAD(ctypes.Structure):
_fields_ = [("dasChan", ctypes.c_ushort),
("temp", ctypes.POINTER(ctypes.c_float))]
Und so funktionierts auch nicht?
Das ctypes.byref kannst du sein lassen, sollte ok sein.
Gruss
Verfasst: Mittwoch 18. März 2009, 19:35
von Jaspar
Hallo rayo,
ich kann Deinen Vorschlag erst morgen ausprobieren.
Ich melde mich dann. Vielen Dank schon mal.
Verfasst: Donnerstag 19. März 2009, 08:54
von Jaspar
Hallo rayo,
ich habe Deine Idee gerade einmal ausprobiert.
Leider ist das Ergebnis unverändert.
Ich erhalte folgende Fehlermeldung:
WindowsError: exception: access violation reading 0x0000000C
Verfasst: Donnerstag 19. März 2009, 09:40
von rayo
Hi
Hast du eine Dokumentation der API?
Vielleicht musst du das Feld temp mit einer bestimmten Anzahl floats erstellen.
Z.B. versucht er auf das 3. Element zuzugreifen und es existiert gar nicht.
Sonst kann ich mir nichts vorstellen.
Gruss
Verfasst: Donnerstag 19. März 2009, 10:03
von Jaspar
Heyho,
inzwischen bin ich einen Schritt weiter.
Wenn ich die Struktur wie ursprünglich definiere:
Code: Alles auswählen
class TCMUXREAD(ctypes.Structure):
_fields_ = [("dasChan", ctypes.c_ushort),
("temp", ctypes.c_float * 1)]
Und dann die API-Funktion folgendermaßen aufrufe:
Code: Alles auswählen
TCMuxRead(driverHandles[0], ctypes.byref(p_tcMuxRead))
Wobei
p_tcMuxRead = ctypes.pointer(tcMuxRead) ist, erhalte ich keinerlei Fehlermeldung mehr. Allerdings ist dann der Wert von
p_tcMuxRead.contents.temp[0] immer gleich 0.0. Das ist aber nachweislich nicht korrekt. Es gibt eine C-Beispielapplikation die die gleiche API-Funktion verwendet und korrekte Temperaturwerte liefert.
Ich bin nach wie vor sehr dankbar für Hilfestellungen.
Liebe Grüße,
Jas
Verfasst: Donnerstag 19. März 2009, 10:09
von rayo
Hi
Kannst du mal das C Beispiel mal hier einfuegen:
http://paste.pocoo.org/
Gruss
Verfasst: Donnerstag 19. März 2009, 10:10
von Jaspar
Hey,
den gesamten Code, oder nur den Funktionsaufruf?
Der gesamte Code ist relativ umfangreich.
[Edit 1] Ich hab mal einen Auszug eingefügt.
[Edit 2] Paste #108614
Verfasst: Donnerstag 19. März 2009, 10:23
von rayo
Hi
Der Datentyp von ptTCMuxRead waere noch interessant. Also das Struct selber (ist ja groesser als deins vom 1. Post) und wie ptTCMuxRead definiert wurde.
Code: Alles auswählen
class TCMUXREAD(ctypes.Structure):
_fields_ = [("dasChan", ctypes.c_ushort),
("temp", ctypes.POINTER(ctypes.c_float))]
temp = ctypes.c_float()
ptTCMuxRead = TCMUXREAD()
TCMUXREAD.temp = ctypes.pointer(temp)
TCMuxRead(driverHandles[0], ctypes.byref(ptTCMuxRead))
Vielleicht so?
Gruss
Verfasst: Donnerstag 19. März 2009, 10:31
von Jaspar
Hey,
static PT_TCMuxRead ptTCMuxRead
Code: Alles auswählen
typedef struct tagPT_TCMuxRead
{
USHORT DasChan;
USHORT DasGain;
USHORT ExpChan;
USHORT TCType;
USHORT TempScale;
FLOAT far *temp;
} PT_TCMuxRead
[Edit 1] Dein letzter Vorschlag führt wieder zu einer
access violation writing 0x00000000
Verfasst: Donnerstag 19. März 2009, 10:57
von rayo
Code: Alles auswählen
class TCMUXREAD(ctypes.Structure):
_fields_ = [("dasChan", ctypes.c_ushort),
("dasGain", ctypes.c_ushort),
("expChan", ctypes.c_ushort),
("tCType", ctypes.c_ushort),
("tempScale", ctypes.c_ushort),
("temp", ctypes.POINTER(ctypes.c_float))]
temp = ctypes.c_float()
ptTCMuxRead = TCMUXREAD()
ptTCMuxRead.dasGain = gwDasGain;
ptTCMuxRead.expChan = gwExpChl;
ptTCMuxRead.tCType = gwTcType;
ptTCMuxRead.tempScale = gwTempScale;
ptTCMuxRead.temp = ctypes.pointer(temp)
TCMuxRead(driverHandles[0], ctypes.byref(ptTCMuxRead))
So sollte das meiner Meinung nach korrekt sein.
Ist LPT_TCMuxRead einfach ein Pointer auf TCMUXREAD?
Gruss
Verfasst: Donnerstag 19. März 2009, 11:06
von Jaspar
Das führt nach wie vor zu einer
access violation writing 0x00000000
rayo hat geschrieben:
Ist LPT_TCMuxRead einfach ein Pointer auf TCMUXREAD?
Ja.
Verfasst: Donnerstag 19. März 2009, 11:37
von rayo
Dann kann ich dir auch nicht weiter helfen.
Vielleicht kannst du bei der ctypes mailing liste fragen.
Gruss
Verfasst: Donnerstag 19. März 2009, 11:41
von Jaspar
Heyho,
vielen Dank für die Hilfe.
Ich werde mal schauen, ob ich bei der Mailingliste weitere Hilfe finde.
Liebe Grüße,
Jas
Verfasst: Donnerstag 19. März 2009, 14:17
von HWK
Etwas komisch ist ja der Far-Pointer auf ein Float. Ist das etwa eine 16-Bit-Bibliothek?
MfG
HWK
Verfasst: Donnerstag 19. März 2009, 15:04
von Jaspar
Hallo HWK,
ich denke nicht, aber prizipiell sollen wohl auch 16-Bit Systeme unterstützt werden.
Verfasst: Freitag 20. März 2009, 13:59
von HWK
Ist far denn bei 32-Bit-Compilern üblich? Wenn es wirklich eine 16-Bit-Lib ist, muss ja auch der Zeiger anders aussehen. Ich glaube nicht, dass ctypes das automatisch anpasst?
MfG
HWK
Verfasst: Freitag 20. März 2009, 14:15
von Jaspar
Nein, soweit ich weiß ist far nicht üblich bei 32-Bit Systemen. Die Bibliothek kapselt aber wohl über Präprozessordirektiven das zugrundeliegende Betriebssystem und ersetzt das Schlüsselwort far dann durch einen Leerstring.
Verfasst: Freitag 20. März 2009, 15:14
von HWK
Nur um sicher zu gehen: driverHandles[0] ist auch ein entsprechender ctypes-Typ wie c_short?
MfG
HWK
Verfasst: Freitag 20. März 2009, 15:43
von Jaspar
driverHandles[0] ist ein c_long.