Autor Beitrag
mfritsch72
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Di 03.12.13 20:58 
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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 433
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 486
Erhaltene Danke: 99

Win7, Win81, Win10
Tokyo, VS2017
BeitragVerfasst: Mi 04.12.13 23:19 
Das sollte doch recht einfach gehen:

ausblenden 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;

_________________
Lies, was da steht. Denk dann drüber nach. Dann erst fragen.
mfritsch72 Threadstarter
Hält's aus hier
Beiträge: 5



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

ausblenden 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 user profile iconMartok: Delphi-Tags hinzugefügt
OlafSt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 486
Erhaltene Danke: 99

Win7, Win81, Win10
Tokyo, VS2017
BeitragVerfasst: 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.

_________________
Lies, was da steht. Denk dann drüber nach. Dann erst fragen.
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 433
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: Do 05.12.13 12:32 
Du brauchs kein Tag. Beispiel:

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

ausblenden 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 user profile iconMartok: Delphi-Tags hinzugefügt
mfritsch72 Threadstarter
Hält's aus hier
Beiträge: 5



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

ausblenden 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 user profile iconMartok: Delphi-Tags hinzugefügt
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 433
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: Do 05.12.13 17:08 
Wieso geht das nicht nicht?

So klappt es bei mir:

ausblenden 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..50of byte;
end;
mfritsch72 Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Fr 06.12.13 15:05 
Gelegentlich sind Lösungen doch ganz einfach, wenn man sie erst mal sieht. Danke.