Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Zeiger auf Prozedur --> Prozedur ausführen
Andreas Pfau - So 28.09.03 13:10
Titel: Zeiger auf Prozedur --> Prozedur ausführen
Hallo,
es gibt da so einige WinAPI-Methoden, die einen Zeiger auf eine Methode wollen (Callback-Methoden). Wie führen die dann die Methoden aus? Ich habe es mal so probiert:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure ShowHelloWorld; stdcall; begin ShowMessage('Hello world!'); end;
procedure TMain.SpeedButton1Click(Sender: TObject); type TProcedure = procedure; PProcedure = ^TProcedure; var Method: PProcedure; begin Method := @ShowHelloWorld; Method^; end; |
Leider führt das nur zu einer Zugrifssverletzung. Was mache ich falsch?
Tino - Mo 29.09.03 09:50
So funktioniert es bei mir:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| procedure ShowHelloWorld; begin ShowMessage('Hello world!'); end;
procedure TForm1.Button1Click(Sender: TObject); type TProcedure = procedure; var Method: TProcedure; begin Method := ShowHelloWorld; Method; end; |
Gruß
Tino
AndyB - Mo 29.09.03 10:47
Der Variablennamen ist hier ein wenig falsch gewählt, da eine Methode immer zu einer Klasse gehört. Mein Vorschlag (kein Muss) wäre hier: Proc oder Func.
Warum dein (Andreas Pfau) Code nicht funktioniert:
Du weist die Adresse der Prozedur ShowHelloWorld dem Zeiger Method zu. Nun dereferenzierst du den Zeiger ("^") und greifst somit auf die ersten 4 Bytes des Codes von ShowHelloWorld zu. Nun versuchst du diese 4 Bytes (die zum Stackframe der Prozedur gehören) als Prozedurzeiger aufzurufen. Das dass im Nirvana landet, ist dann wohl klar.
Des weiteren hast du TProcedure falsch deklariert. ShowHelloWorld benutzt die Aufrufkonvention stdcall. TProcedure hingegen den Vorgabewert register. Da du hier weder Parameter noch Rückgabewert hast, passiert hier zwar nichts. Das kann sich aber schlagartig ändern.
Andreas Pfau - Mo 29.09.03 15:55
Hallo,
vielen Dank, es klappt!
Nur noch was: Ich will desweiteren, dass ich vollkommen variante Parameter habe, also z.B. so:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure ShowHelloWorld(Str: string); begin ShowMessage(Str); end;
procedure TMain.SpeedButton1Click(Sender: TObject); Proc: procedure; begin Proc := ShowHelloWorld; Proc('Helo World'); end; |
Das geht nicht, logo. Aber, wäre da irgendiwe machbar? Dass ich also eine beliebige Parameterliste übergebe? Oder geht so was net? Klar, ich könnte einen "array of const" übergeben, und je nach Methode die Parameter unterschiedlich auswerten, aber geht es auch so wie oben angedeutet?
maximus - Mo 29.09.03 16:07
Nein...so wie angedeutet wirst du kein glück haben :? Beim aufruf einer procedure wird eine parameterliste, mit einer festen grösse, erwartet. Ausserdem kommst du am compiler nicht vorbei, der dir verbietet abweichende parameter zu übergeben!
mit nem array pointer wäre aber eine reale möglichkeit...naja, halt auch nicht so schön..
barfuesser - Mo 29.09.03 17:11
| Andreas Pfau hat folgendes geschrieben: |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure ShowHelloWorld(Str: string); begin ShowMessage(Str); end;
procedure TMain.SpeedButton1Click(Sender: TObject); var Proc: procedure; begin Proc := ShowHelloWorld; Proc('Helo World'); end; |
|
sollte so aussehen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure ShowHelloWorld(AStr: string); begin ShowMessage(Str); end;
procedure TMain.SpeedButton1Click(Sender: TObject); var Proc: procedure<span style="color: red">(AStr: String)</span>; begin Proc := ShowHelloWorld; Proc('Helo World'); end; |
barfuesser
Andreas Pfau - Mo 29.09.03 17:14
Hallo,
@maximus, nicht schön, aber es macht ja nix aus... das sind nur ("nur") ein paar Nanosekunden, wenn überhaupt, weil ich über mehr Speicheradressen gehen muss... Aber so werde ich es wohl machen müssen.
So, damit wäre das Thema erledigt. Vielen Dank für eire Hilfe!
maximus - Mo 29.09.03 17:53
@Andreas: ja genau!
@barfuesser: immer erst schön lesen...dann pos(t)en *g* ...das war von andreas schon so beabsichtigt.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 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!