Hi,
zuerst mal guten Tag hier im Forum. Ich bin Neuling in Sachen Pascal und komme aus dem C/C++ Lager. Im Grunde ist der Umstieg kein Problem, doch an einer für mich sehr wichtigen Sache hänge ich fest. Es ist nicht ganz einfach, das Problem so zu schildern, dass ich richtig verstanden werde, aber ich versuch's mal, wobei ich einiges stark vereinfache.
Also, ich habe eine Unit "Winsys", in der u.a. die Eventschleife von SDL untergebracht ist. Tritt ein Ereignis ein, z.B. ein Tastendruck, wird aus dieser Schleife heraus der Event-Handler "Keyhandler" aufgerufen. So weit - so gut - so einfach. Aber es gibt zwei Besonderheiten:
1. Das Programm arbeitet mit verschiedenen Programmmodi, die jeweils eine eigene Implementation des Key-Handlers enthalten.
2. Jeder Programmmodus ist in einer eigenen Unit untergebracht; damit sind auch die Key-Handler nicht in der Unit Winsys enthalten, sondern in anderen Programmeinheiten.
Im Grunde "weiß" die Loopfunktion nicht mal, welcher Key-Handler gerade aktiv sein soll, und dennoch muss das Ereignis an die richtige Adresse weitergeleitet werden. Es gibt vielleicht die Möglichkeit, mit abstrakten Klassen zu arbeiten, aber das Verfahren ist ziemlich unübersichtlich. Wesentlich eleganter ist der Weg über Funktionspointer. Dazu wird in Winsys ein Array mit Funktionspointern angelegt, und jeder Modus trägt dort nach dem Programmstart den Zeiger auf seinen Keyhandler ein. Über eine einfache Enum-Variable kann von der Loop je nach Modus die passende Funktion selektiert und aufgerufen werden. Ebenso könnte man natürlich auch eine einzige Funkionsvariable nehmen und dort bei einem Moduswechsel in der Init-Phase den aktuellen Keyhandler eintragen. Beides funktioniert unter C++ hervorragend und ist einfach zu implementieren, doch ob das auch in Pascal geht (und wie!) weiß ich nicht. Ich rede gewohnheitsmäßig von Funktionen, meine damit natürlich auch Prozeduren, das sollte egal sein.
- Wie könnte die Typdeklaration der Funktion aussehen? Als Parameter wird ein Record (sagen wir mal TKeyParams) übergeben.
- Wie sieht die Variable aus, die die wechselnden Funktionszeiger aufnimmt?
- Wie wird die Funktion in dieser Variablen von der Winsys-Loop aufgerufen?
- Wie lautet der Term, mit dem ein Funktionszeiger aus der Modus-Unit übermittelt wird?
Nun verderbt mir bitte nicht den Spaß an Pascal, indem ihr mir mitteilt, dass das so nicht geht.
Gruß
Henlambert
Problem rund um Funktionspointer
-
- Beiträge: 12
- Registriert: Di 7. Mai 2013, 18:32
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Problem rund um Funktionspointer
henlambert hat geschrieben:- Wie könnte die Typdeklaration der Funktion aussehen? Als Parameter wird ein Record (sagen wir mal TKeyParams) übergeben.
- Wie sieht die Variable aus, die die wechselnden Funktionszeiger aufnimmt?
- Wie wird die Funktion in dieser Variablen von der Winsys-Loop aufgerufen?
- Wie lautet der Term, mit dem ein Funktionszeiger aus der Modus-Unit übermittelt wird?
Code: Alles auswählen
type
// Parameter-Typen müssen natürlich vorab bekannt sein
TKeyParams = record
myvar1: Integer; // dein Inhalt
end;
Name = procedure/function (Parameter)[: Ergebnistyp] [of object]; [modifier]
Code: Alles auswählen
// Funktions-Typ für eine normale Prozedur
TKeyCallback = procedure (const mypar: TKeyParams);
// Funktionstyp für eine normale Funktion
TKeyCallbackFunc = function (const mypar: TKeyParams): Integer;
// Funktionstyp für eine Prozedur-Methode eines Objektes
TKeyCallbackObj = procedure (const mypar: TKeyParams) of object;
Code: Alles auswählen
// Variable für den Prozedurzeiger deklarieren
var
pproc: TKeyCallback;
// natürlich geht das auch mit einem Array:
pprocArray: array[0..2] of TKeyCallback;
// Der Key-Handler
procedure MyKeyHandler(const mypar: TKeyParams);
begin
writeln('Hallo Welt!');
end;
// dann geht die Zuweisung so (Der Operator @ liefert in Pascal die Adresse des folgenden Ausdrucks)
pproc := @MyKeyHandler;
pprocArray[0] := @MyKeyHandler;
// Der Aufruf erfolgt ganz normal:
pproc(myvar);
// bzw.
pprocArray[0](myvar);
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
-
- Beiträge: 12
- Registriert: Di 7. Mai 2013, 18:32
Re: Problem rund um Funktionspointer
Danke, das war eine präzise und erschöpfende Antwort.
Es funktioniert hervorragend. Ich kann übrigens allen, die nicht mit der LCL, sondern mit einer eigenen Eventschleife und z.B. SDL und OpenGL arbeiten, das Verfahren empfehlen. Es kommt mit minimalem Code aus, ist schnell und vor allem beliebig erweiterbar.

Es funktioniert hervorragend. Ich kann übrigens allen, die nicht mit der LCL, sondern mit einer eigenen Eventschleife und z.B. SDL und OpenGL arbeiten, das Verfahren empfehlen. Es kommt mit minimalem Code aus, ist schnell und vor allem beliebig erweiterbar.