![]() |
TInterfaceList und lokale Referenzen
Hi zusammen,
hab gerade was, was mich extrem stutzig macht. Kurze Erlaeuterung: Ich lade Plugin-DLLs und speichere deren Interfaces(ITWPLugin) in eine TInterfaceList(FPLugins). In einer Funktion UnloadAllPlugins sollen die Eintraege in der Liste geloescht und die jeweilige DLL entladen werden (Handle zur DLL wird im Plugin gespeichert). Folgender Code funktioniert (ist aber sehr unschoen):
Delphi-Quellcode:
UnloadAllPlugins ruft quasi die Hilfsfunktion RemovePlugins auf, die in einer TStringList die Handles zurueckliefert, die entladen werden koennen und entlaedt diese entsprechend. Wenn ich jetzt aber versuche das in eine Funktion zu packen, so bekomme ich 'ne AV beim FreeLibrary. Ich kann mir das nur so erklaeren, dass im Scope von RemovePlugins zusaetzliche Referenzen zu den Plugin-Interfaces entstehen. Deshalb gibt's die AV, ich versuche halt eine Library zu entladen, von der noch Objekte vorhanden sind. Verlasse ich den Scope von RemovePlugins, so werden diese Referenzen natuerlich geloescht und die Objekte korrekterweise zerstoert.
function TTWPluginManager.RemovePlugins: TStringList;
var i: Integer; LHandle: THandle; LPlugin: ITWPlugin; begin result := TStringList.Create; for i := FPlugins.Count - 1 downto 0 do begin LHandle := (FPlugins.Items[i] as ITWPlugin).Handle; result.Add(inttostr(LHandle)); FPlugins.Delete(i); end; end; function TTWPluginManager.UnloadAllPlugins: Boolean; var i: Integer; LHandle: THandle; HandleList: TStringList; begin HandleList := RemovePlugins; for i := 0 to HandleList.Count - 1 do begin LHandle := StrToInt(HandleList[i]); FreeLibrary(LHandle); end; HandleList.Free; end; Aber an welcher Stelle schaffe ich mir diese lokalen Referenzen ? Bin fuer jeden Hinweis dankbar. Hab zwar diesen funktionierenden Workaround, aber gerade an 'ner Pluginschnittstelle will ich nicht direkt mit Pfusch anfangen ;-) Gruesse, Lizzy |
Re: TInterfaceList und lokale Referenzen
Hallo!
Meine Vermutung ist, dass die Zeile
Delphi-Quellcode:
den Fehler verursacht. Der Referenzzähler müsste beim Ausführen hochgezählt werden und wird wohl erst nach Beenden der Routine frei gegeben.
LHandle := (FPlugins.Items[i] as ITWPlugin).Handle;
Versuche es doch einmal so:
Delphi-Quellcode:
Getestet habe ich es nicht.
...
for i := FPlugins.Count - 1 downto 0 do begin LPlugin := (FPlugins.Items[i] as ITWPlugin); LHandle := LPlugin.Handle; result.Add(inttostr(LHandle)); FPlugins.Delete(i); End; LPlugin := Nil; ... |
Re: TInterfaceList und lokale Referenzen
Kommt der Interfacezeiger (ITWPLugin) aus der DLL? Wie schaut die entsprechende Funktion aus der DLL aus?
|
Re: TInterfaceList und lokale Referenzen
@Andreas
Der Code arbeitet so wie gepostet schon korrekt. Unschoen ist nur, dass ich auf diese Hilfsfunktion angewiesen bin und nicht alles in einer Prozedur ausfuehren kann. Zitat:
Delphi-Quellcode:
TExamplePlugin ist dabei abgeleitet von einer Klasse TTWPlugin, die das Interface ITWPlugin implementiert.
function GetPlugin(APluginManager: ITWPluginManager): ITWPlugin;
begin result := TExamplePlugin.Create(APluginManager); end; Gruesse, Lizzy |
Re: TInterfaceList und lokale Referenzen
Vielleicht funktioniert es so
Delphi-Quellcode:
Ich halte noch an der These fest, dass
function TTWPluginManager.UnloadAllPlugins: Boolean;
Var i: Integer; LHandle: THandle; LPlugin: ITWPlugin; begin for i := FPlugins.Count - 1 downto 0 do begin LPlugin := (FPlugins.Items[i] as ITWPlugin); LHandle := LPlugin.Handle; LPlugin := Nil; FPlugins.Delete(i); FreeLibrary(LHandle) end; End
Delphi-Quellcode:
den Referenzzähler hochzählt und zu spät wieder herunterzählt.
LHandle := (FPlugins.Items[i] as ITWPlugin).Handle;
:duck: |
Re: TInterfaceList und lokale Referenzen
Zitat:
|
Re: TInterfaceList und lokale Referenzen
Zitat:
Ich geb Dir jetzt mal zu 50% Recht ;-). Okay, sogar etwas mehr als 50%. Es ist in der Tat so, dass genau in dieser Zeile der ... aeh... nein... DIE Referenzzaehler hochgezaehlt werden. Und zwar passiert naemlich Folgendes: 1. Holen des Interfaces aus FPlugins -> Erhoeht Ref.-Zaehler fuer IInterface 2. Cast auf ITWPlugin -> Erhoeht Ref.-Zaehler fuer ITWPlugin Dann ist auch das klar:
Delphi-Quellcode:
Referenzzaehler fuer ITWPlugin geht natuerlich auf 0. Aber: Referenzzaehler fuer IInterface wird erst nach beenden der Prozedur runtergezaehlt und dementsprechend erst dann das Objekt zerstoert.
procedure Foo();
var x: ITWPlugin; begin x := FPLugins[0] as ITWPlugin; x := nil; end; In dem Sinne, Danke fuer die Antworten. Jetzt kann ich wieder ruhig schlafen *g*. Thema ist somit geklaert :) Gruesse, Lizzy |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:36 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz