Autor Beitrag
peeage
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 50



BeitragVerfasst: Fr 23.01.09 16:46 
Hallo zusammen !

Ich nutze in meiner Klasse eine Komponente, deren ich den Pointer zu einer Prozedur in meiner Klasse bekanntgebe. Die Komponente ruft dann regelmäßig meine Prozedur auf ( Callback / Event ). Das klappt alles perfekt. Nun bietet meine Klasse auch eigene Events / CallBacks an, so das andere Klassen - die meine Klasse nutzen - auch bei bestimmten Ereignissen informiert werden. Dies klappt auch wunderbar... NUR wenn ich MEINE CallBackprozedur ( sprich: Die Prozedur in der Klasse welche bei Ereignissen aus meiner Klasse informiert werden möchte) innerhalb der CallBackprozedur aufrufe, die in meiner Klasse durch die Komponente ausgelöst wurde, kommt es zu einer Zugriffsverletzung.

Ist jemand auch schonmal über das Problem gestoßen?


Gruß
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 23.01.09 18:54 
Ohne etwas Code ist es schwer dazu etwas zu sagen...
Wie sieht der Aufruf aus, wie die Deklaration?

Kommt die Zugriffsverletzung an Adresse 0 oder einer anderen?
peeage Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 50



BeitragVerfasst: Fr 23.01.09 20:06 
Mir ist gerade aufgefallen das ich von einer Callback- Prozedur allgemein auf keine Variablen aus der eigenen Klasse zugreifen kann ( sei es privat, public ... )

Hier ein Beispiel:

Klasse die das Ereignis bekannt gibt:

ausblenden 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:
unit Unit2;

interface

type TMyEvent = procedure of object;

     TMyClass = Class
      private
        FMyEvent : TMyEvent;
      public
        constructor Create;
        procedure doEvent;
        property MyEvent : TMyEvent read FMyEvent write FMyEvent;
      end;

implementation

constructor TMyClass.Create;
Begin
  inherited Create;
end;

procedure TMyClass.doEvent;
Begin
  if Assigned( FMyEvent ) then
    FMyEvent;
end;

end.



Klasse deren Callback- Prozedur aufgerufen wird ( Hier als Beispiel eine TForm- Klasse ):
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:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    str : String;
    procedure MyEvent;
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1   : TForm1;
  MyClass : TMyClass;

implementation

{$R *.dfm}

procedure TForm1.MyEvent;
Begin
  ShowMessage(str);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  MyClass := TMyClass.Create;
  @MyClass.MyEvent := @TForm1.MyEvent;
  MyClass.doEvent;
end;

end.




TForm1.MyEvent wird aufgerufen. Hier soll der String "str" ausgegeben werden, nur leider kommt es hier zu einer Fehlermeldung.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 23.01.09 20:41 
user profile iconpeeage hat folgendes geschrieben Zum zitierten Posting springen:
TForm1.MyEvent wird aufgerufen. Hier soll der String "str" ausgegeben werden, nur leider kommt es hier zu einer Fehlermeldung.
Weil das Event nicht im Kontext des Formulars aufgerufen wird sozusagen. Versteckt wird glaube ich die Instanz mitgeliefert, und die ist in dem Fall nil.
(Werte einfach mal Self aus mit Strg + F7.)

Warum nicht einfach so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.MyEvent;
Begin
  ShowMessage(Form1.str);
end;
;-)
peeage Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 50



BeitragVerfasst: Fr 23.01.09 21:06 
Hmmm.. stimmt. So geht es in meinem Beispiel.

Nur habe ich in meiner Klasse ( nicht das Beispiel mit der TForm- Klasse ) keine Referenz auf die aktuelle Instanz meiner Klasse ( wie im Beispiel "Form1" ). Die Referenz auf die Instanz meiner Klasse besitzt nur die Klasse, die meine Klasse Instantiert.
Ich kann innerhalb der instantiierten Klasse nur mittels "self" auf die aktuelle Instanz der Klasse zugreifen, oder? Nur wenn ich das nun so mache -> ShowMessage( self.str ) ... Dann bekomm ich auch wieder diesen Fehler.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 23.01.09 21:20 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
und die ist in dem Fall nil.
(Werte einfach mal Self aus mit Strg + F7.)
Ich sagte ja, dass genau das Self das Problem ist. Du darfst den Eventhandler nicht als Teil der Klasse sehen und das entsprechend programmieren.
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 25.01.09 18:39 
Verwende:
ausblenden Delphi-Quelltext
1:
  MyClass.MyEvent := MyEvent;					

statt
ausblenden Delphi-Quelltext
1:
  @MyClass.MyEvent := @TForm1.MyEvent;					

Und wenn die eigentliche Instanz unwichtig ist, dann mit class procedures arbeiten, dann heisst es:
ausblenden Delphi-Quelltext
1:
  MyClass.MyEvent := TForm1.MyEvent; // in TForm1: class procedure MyEvent;