Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - C-Struct Übersetzungsproblem
mfritsch72 - Di 03.12.13 20:58
Titel: C-Struct Übersetzungsproblem
Hallo,
ich habe ein Problem mit der Übersetzung folgender Struct einer H-Datei für den Zugriff auf eine DLL:
struct {
...
uint16 (*SendCommand)(void*, uint8 xCt, uint16* xDat, uint8 rCt, uint16* rDat);
...
}
Soweit ich es sehe brauch ich da einen Pointer auf eine Function, die mir ein word zurückgibt.
Nur ist die SendCommand wie folgt definiert:
uint16 SendCommand(AxisInterface axis_intf, uint16 OPCode);
Wie passt dies zusammen ?
Vielen Dank schon mal.
mandras - Di 03.12.13 21:50
Das hat beides nicht viel miteinander zu tun, da auch die Parameterliste verschieden ist.
Ohne weitere Infos wird man Dir auch nicht helfen können denke ich.
mfritsch72 - Mi 04.12.13 16:01
Ja, ist mir leider klar. Aber der Treiberhersteller ist offensichtlich ein ziemlicher C Freak,
der ohne Rücksicht auf typ-sichere Sprachen arbeitet. Der verpackt in die struct nicht nur
eine sondern gleich circa 10 verschiedene Funktionsaufrufe.
D.h. der Eintrag (*SendCommand)... in der struct wird per pointer auf unterschiedliche
Funktionen mit unterschiedlichen Parametern gesetzt. Das mag ja in C gehen, aber wie ich das
in Delphi verpacken soll, ist mir ein Rätsel.
uint16 SendCommand(AxisInterface axis_intf, uint16 OPCode);
uint16 SendCommandA(void*, uint8 xCt, uint16* xDat, uint8 rCt, uint16* rDat);
uint16 SendCommandB(void*, uint16* xDat, uint8 rCt, uint16* rDat);
usw. ( insgesamt noch viele weitere Funktionen, die aufgerufen werden... )
OlafSt - Mi 04.12.13 23:19
Das sollte doch recht einfach gehen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| type TFunnyProc1 = function(axis_intf: TAxisInterface; Opcode: word): Word; TFunnyProc2 = function(P: Pointer; xCt: byte; var xDat: Word; rCt: byte; var rDat: Word); ... end;
TProcRec = record SendCommand: TFunnyProc1; SendCommandA: TFunnyProc2; ... end; |
mfritsch72 - Do 05.12.13 10:06
Leider geht es eben nicht so einfach, da den Aufbau des Records ja von der DLL vorgegeben habe. Es handelt sich bei der DLL ja um
einen fertigen Treiber zum Ansteuern einer PCI Karte.
Und ich habe dummerweise nur den einen Pointer auf eine Function zur Verfügung, weil die DLL, die ansprechen muss, eben
genau an dieser Stelle nur einen Pointer auf eine Funktion erwartet. Diese Funktion kann aber verschiedene Parametersätze
haben. ( SendCommand, SendCommandA, ... SendCommandH )
Deshalb kann ich leider nicht mehrere Pointer in den Record einbauen, weil ja dann die übergebenen Functionen an einer
anderen Stelle im Record stehen.
Ich hatte schon an einen Record mit varianten Inhalt gedacht:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| TMyStruct = record case TFunnyProcSet of SendCmd: TFunnyProc1; SendCmdA : TFunnyProd2; ... end; |
Aber das geht auch nicht, da ich ja kein TAG zur Auswahl der Funktionen habe. Und ein Set of Functions, damit der
Compiler autom. die richtige Funktion auswählt, ist auch nicht möglich. ( Wenigstens kann ich es nicht ... )
Hier noch mal eine Zusammenfassung meines Problems:
Ich brauche eine Speicherstelle im Record, in der ich einen Pointer auf eine beliebige Funktion setzen kann, die
beliebige ( insgesamt habe ich bisher 14 Varianten gefunden ) Parameter übernehmen und zurückgeben wird.
Moderiert von
Martok: Delphi-Tags hinzugefügt
OlafSt - Do 05.12.13 12:05
Wenn ich das richtig verstehe, dann glaubst du, das in der DLL nur eine einzige Routine existiert, die dann von selbst erkennt, welche Parameter da so angegeben sind.
Mit Verlaub, aber sowas ist selbst in C nicht machbar.
mandras - Do 05.12.13 12:32
Du brauchs kein Tag. Beispiel:
Delphi-Quelltext
1: 2: 3: 4:
| t:record case integer of 1: (a:integer); 2: (b:byte); end; |
allerdings darf nach dem varianten Teil nichts "normales" kommen.
Das kann man umschiffen, indem der variante Record innerhalb eines "Normalen" eingeschachtelt wird.
Dann ist die Länge (der Speicherbedarf) des varianten Teils gleich seines größten:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| type ti=record case integer of 1: (a:integer); 2: (b:byte); end;
var t:record t1: ti; t2:boolean; end; |
Moderiert von
Martok: Delphi-Tags hinzugefügt
mfritsch72 - Do 05.12.13 15:42
@OlafSt:
Mir ist schon klar, dass C so was auch nicht macht. Ich würde eher sagen, dass C sowas ziemlich egal ist, da C sich ja nicht wirklich um Typen kümmert.
Die Struktur ist ein Container für die unterschiedlichsten Funktionen, die die Karte ausführen kann. Deshalb muss ich da einen Pointer auf
verschiedene Funktionen eintragen. Wenn ich es richtig verstehe, stehen in der Struct nur Pointer auf Funktionen. Also könnte ich etwa
folgendes machen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| TMyStruct = record pSendCommand : pointer; pClose : pointer; pGetStatus : pointer; pIsReady : pointer; pHasInterrupt : pointer; pHasError : pointer; pHardReset : pointer; bHasDPRAM : integer; pReadDPRAM : pointer; pWriteDPRAM : pointer; end; |
Nur dann caste ich mich ja zu Tode. Rein für den SendCommand gibt es 14 verschiedene Definitionen. Für GetStatus gibts 2 Definition usw.
Bis ich da alle benötigten Kombinationen getippt habe, ist Weihnachten 2014. :-)
@mandras
Geht aber leider nicht mit Funktionen und außerdem kommt danach noch was "normales". Trotzdem: Danke.
Moderiert von
Martok: Delphi-Tags hinzugefügt
mandras - Do 05.12.13 17:08
Wieso geht das nicht nicht?
So klappt es bei mir:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| type TFunnyProc1 = function(axis_intf: byte; Opcode: word): Word; TFunnyProc2 = function(P: Pointer; xCt: byte; var xDat: Word; rCt: byte; var rDat: Word):char;
TProcRecI = record case integer of 0:( SendCommand: TFunnyProc1); 1:( SendCommandA: TFunnyProc2); end;
TProcRecE = record funcs: TProcRecI; dummy: integer; sonstwas: array[0..50] of byte; end; |
mfritsch72 - Fr 06.12.13 15:05
Gelegentlich sind Lösungen doch ganz einfach, wenn man sie erst mal sieht. Danke.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!