Autor Beitrag
Andreas Pfau
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 997



BeitragVerfasst: So 28.09.03 13:10 
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:
ausblenden 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?

_________________
Life is a bad adventure, but the graphic is really good!
Tino
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: Mo 29.09.03 09:50 
So funktioniert es bei mir:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: 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.

_________________
Ist Zeit wirklich Geld?
Andreas Pfau Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 997



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

_________________
Life is a bad adventure, but the graphic is really good!
maximus
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 896

Win XP, Suse 8.1
Delphi 4/7/8 alles prof
BeitragVerfasst: 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..

_________________
mfg.
mâximôv
barfuesser
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 324



BeitragVerfasst: Mo 29.09.03 17:11 
Andreas Pfau hat folgendes geschrieben:
ausblenden 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:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 997



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

_________________
Life is a bad adventure, but the graphic is really good!
maximus
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 896

Win XP, Suse 8.1
Delphi 4/7/8 alles prof
BeitragVerfasst: 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.

_________________
mfg.
mâximôv