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:
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:
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:
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:
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.
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