Autor Beitrag
Carlo91
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 20



BeitragVerfasst: So 12.09.10 13:26 
Hallo,
nach langer Delphi pause arbeite ich jetzt wieder an einem kleinen privaten projekt und schon gibt es die ersten probleme^^ Ich programmiere ein Client programm, der Client emfängt vom Server befehle und parameter, in diesem Format 'befehl#parameter1#parameter2#parameterN'. Ich Splite mir den String zu einem String array, soweit funktioniert auch alles! Dann habe ich für jeden befehl eine Methode erstellt also:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
type
TClient = class(TForm)
...
procedure befehl(parameter: array of String);
procedure befehl1(parameter: array of String);
procedure befehl2(parameter: array of String);
...
end;


Wenn ich jetzt per MethodAddress mir "die Adresse des befehls" hole und die methode dann aufrufe bekomme ich in der Methode zugriffsverletzungen wenn diese auf andere Objekte des Clients zugreifft (z.B. Button1). Ich habe mal ein kleines Beispiel programm erstellt:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure clickbtn(data: String);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  cb: procedure (data: Stringof Object;
begin
  @cb :=Nil;
  @cb :=MethodAddress('clickbtn');
  if (@cb <> Nilthen
  begin
    cb('test');
  end;
end;

procedure TForm1.clickbtn(data: String);
begin
  ShowMessage(data); //funktioniert
  Button2.Enabled :=True; // zugriffsverletzung
  Button2.Click;
  Button2.Enabled :=False;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ShowMessage('Hallo Welt!');
end;

end.


Meine frage ist jetzt was mache ich falsch? Und habe ich die funktionweise von MethodAddress überhaupt richtig verstanden? Ich freue mich auf eure antworten und hilfe ;-)!


Mit freundlichen Grüßen

Thorben
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: So 12.09.10 14:53 
Hallo,

das funktioniert auch ohne Methoaddress:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure TForm1.Button1Click(Sender: TObject);
var
  cb: procedure (data: Stringof Object;
begin
  cb :=clickbtn; // !!
  if (@cb <> Nilthen
  begin
    cb('test');
  end;
end;
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 12.09.10 15:12 
user profile iconCarlo91 hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
  cb: procedure (data: Stringof Object;
begin
  @cb :=Nil;
  @cb :=MethodAddress('clickbtn');
  if (@cb <> Nilthen
  begin
    cb('test');
Das Problem ist ganz einfach:
Du holst dir die Adresse, dir fehlt aber der zweite Zeiger, nämlich der zu den Daten sprich deinem Objekt.

Denn wie der Name dieser Klassenmethode bereits sagt bekommst du nur die Adresse der Methode, mehr nicht. Das heißt du musst das ganze z.B. in eine TMethod Variable packen und dort zusätzlich zu der Codeadresse, die du über MethodAdress bekommst, auch noch den Datenpointer, also den Objektpointer ausfüllen.

Dann kannst du auch auf Daten des Objekts zugreifen.

// EDIT:
Was schreib ich hier eigentlich, steht doch alles in der Dokumentation... :roll:
docwiki.embarcadero....Object.MethodAddress
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: So 12.09.10 15:34 
Hallo, und bitte sehr, warum funktioniert das mit meinem Beispiel? Die Prozedur Clickbtn ist ja - soweit ich weiß - kompatibel mit einer Prozedurvariablen, wie sie in der Prozedur Button1click definiert wurde. Daher müsste das Beispiel durch einfache Zuordnung der Prozedur zur Variablen cb klappen. Ich habe es ausprobiert. Es klappt.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 12.09.10 16:08 
user profile iconTranx hat folgendes geschrieben Zum zitierten Posting springen:
Hallo, und bitte sehr, warum funktioniert das mit meinem Beispiel? Die Prozedur Clickbtn ist ja - soweit ich weiß - kompatibel mit einer Prozedurvariablen, wie sie in der Prozedur Button1click definiert wurde.
Das ist gerade keine Prozedurzeiger, sondern ein Methodenzeiger. Ein Methodenzeiger wie er dort deklariert ist enthält die Adresse plus die Daten. Also die Adresse der Prozedur plus die des Objekts, zu dem die Methode gehört.

Da du die Methode diesem Methodenzeiger direkt zuweist, weist du auch das Objekt mit zu. Deshalb klappt das dort.
Carlo91 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 20



BeitragVerfasst: So 12.09.10 17:00 
Danke, mit TMedthod funktioniert es in meinem Beispiel projekt! In meinem richtigen Projekt zwar noch nicht aber den fehler werde ich wohl selbst finden.


Mit freundlichen Grüßen

Thorben