Autor Beitrag
Shaddow89
Hält's aus hier
Beiträge: 15



BeitragVerfasst: Do 30.10.08 13:49 
Hi,
ich habe vor einer Weile mal mit Java angefangen und bin auf die Vorteile von Interfaces gestossen. Kurz darauf habe ich bemerkt, dass man die auch in Delphi verwenden kann und daher habe ich mein bisheriges Projekt, eine 3D Engine, mit Interfaces ausgestattet.

Ich habe einen Eventmanager, der alle Events (Keydown, Mousebewegungen, Klicks, Exit usw usw usw) registriert und weiterleitet. Für jedes Event verfügt er über eine Liste, in der Interfaces abgelegt sind.

Wenn ich nun zb eine Szene erstellen und das Interface IKeyListener implementiere, dann kann ich diese Szene dank ihres Interfaces in meinem Eventlistener registrieren. Wenn mein Eventlistener nun ein KeyDown event registriert, ruft er automatisch die Keydownmethode der Szene, die im Interface definiert ist, auf. Soviel zur Vorgeschichte. hier erstmal etwas Quellcode, damit das klarer wird:

Die Listenerdefinition:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
type
  IKeyListener = interface(IInterface)
    ['{BB9DB2E4-B01D-445E-9778-5742CD29ED7C}']
    procedure OnKeyDown   (event : TKeyEvent);
    procedure OnKeyUp     (event : TKeyEvent);
    procedure OnKeyPressed(event : TKeyEvent);
  end;


Die Szenendefinition:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
type
  TWorldScene = class (TGL_Scene, IKeyListener)
  private
    points: Array of TGLVector3f;
    tmp:    Array of TGLVector3f;

  public
    constructor Create();              override;
    procedure Init;                    override;
    procedure Render;                  override;
    procedure Update (aTime: Integer); override;
    procedure Release;                 override;
    destructor Destroy();              override;

    procedure OnKeyDown   (event : TKeyEvent);
    procedure OnKeyUp     (event : TKeyEvent);
    procedure OnKeyPressed(event : TKeyEvent);
  end;


Wenn ich nun in meinem Hauptprogramm die Szene per:
ausblenden Delphi-Quelltext
1:
  EventManager.AddKeyListener(world);					

registriere, dann wird fortan bei jedem Tastendruck die entsprechenden Methoden aus der Szene aufgerufen..


Nun das Problem:
Bei der Erstellung der Szene muss ich die Szene in meinem Szenenmanager registrieren. Das heisst das Objekt world wird automatisch doppelt registriert. Einmal in meinem Szenenmanager, weil es von Scene erbt und einmal im Eventmanager, weil es den IKeyListener implementiert.

Wenn ich das Programm allerdings beende und alle Objekte zerstört werden, treten Fehler auf, die aus irgendeinem Grund mit den Interfaces zusammenhängen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
destructor TGL_SceneManager.Destroy;
var i : Integer;
begin
  ReleaseScene();
  for i := 0 to lScenes.Count - 1 do
  begin
    (lScenes.Objects[i] as TGL_Scene).Destroy;
  end;
  lScenes.Destroy;
end;
end.


In diesem Destructor des ScenenManagers werden alle Szenen, die in der THashedStringList lScenes abgelegt sind, zerstört. In dem Moment, in dem das Programm versucht, die Worldscene zu zerstören, bekomme ich eine EInvalidPointer mit der Meldung "Ungültige Zeigeroperation" und zwar genau in der Zeile begin des Destruktors.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
destructor TWorldScene.Destroy;
begin
  inherited Destroy;
end;



Ich bastel hier jetz schon ewig dran rum und weiss einfach nicht warum das nicht geht. Nicht zuletzt könnte das aber daran liegen, dass es bei Interfaces womöglich irgendeine Spezifikation gibt, von der ich nichts weiß. Prinzipiell sind die Quelle, die ich im Internet zu Delphiinterfaces finde, aber ziemlich Bescheiden..


Vielleicht hat ja jemand eine Idee
danke
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: Do 30.10.08 15:38 
Man sollte niemals selbst Destroy aufrufen, nimm FreeAndNil, das prüft ob das Objekt schon nil ist.
Shaddow89 Threadstarter
Hält's aus hier
Beiträge: 15



BeitragVerfasst: Do 30.10.08 17:53 
Okay also ich hab mal alle Destroys auf Free umgestellt, weil es FreeAndNil scheinbar nicht gibt

Der Fehler jedoch bleibt bestehen
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Do 30.10.08 20:37 
Alle Delphi-Interfaces sind auch COM-Interfaces und somit von IUnknown abgeleitet, welche Methoden zur Referenzzählung deklarieren. Delphi ruft diese Methoden intern immer auf wenn Interface-Zeiger kopiert, gelöscht etc werden. Damit soll sichergestellt werden, dass das Objekt wirklich solange existiert, solange es noch Referenzen darauf gibt. Sobald die letzte Referenz gelöscht wird ist der reference counter 0 und das Objekt gibt sich selbst frei.

Such einfach mal hier im Forum, da müsste sich noch einiges an weiterer Information dazu finden...

Gruß, Motzi

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
Lossy eX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1048
Erhaltene Danke: 4



BeitragVerfasst: Fr 31.10.08 10:46 
Bin zu faul das hier rein zu posten oder doppelt zu schreiben. ;)

Crossposting auf delphigl.com.

_________________
Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.