Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi TInterfaceList und lokale Referenzen (https://www.delphipraxis.net/71719-tinterfacelist-und-lokale-referenzen.html)

lizardking 19. Jun 2006 23:29


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

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

andreash 25. Jun 2006 15:53

Re: TInterfaceList und lokale Referenzen
 
Hallo!

Meine Vermutung ist, dass die Zeile
Delphi-Quellcode:
  LHandle := (FPlugins.Items[i] as ITWPlugin).Handle;
den Fehler verursacht. Der Referenzzähler müsste beim Ausführen hochgezählt werden und wird wohl erst nach Beenden der Routine frei gegeben.

Versuche es doch einmal so:

Delphi-Quellcode:
...
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;
...
Getestet habe ich es nicht.

Bernhard Geyer 25. Jun 2006 20:46

Re: TInterfaceList und lokale Referenzen
 
Kommt der Interfacezeiger (ITWPLugin) aus der DLL? Wie schaut die entsprechende Funktion aus der DLL aus?

lizardking 2. Jul 2006 22:41

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:

Zitat von Bernhard Geyer
Kommt der Interfacezeiger (ITWPLugin) aus der DLL? Wie schaut die entsprechende Funktion aus der DLL aus?

Jepp, der Interface-Zeiger kommt aus der DLL. Die exportierte Funktion dabei ist recht unspektakulaer:

Delphi-Quellcode:
function GetPlugin(APluginManager: ITWPluginManager): ITWPlugin;
begin
  result := TExamplePlugin.Create(APluginManager);
end;
TExamplePlugin ist dabei abgeleitet von einer Klasse TTWPlugin, die das Interface ITWPlugin implementiert.

Gruesse,

Lizzy

andreash 5. Jul 2006 21:45

Re: TInterfaceList und lokale Referenzen
 
Vielleicht funktioniert es so
Delphi-Quellcode:
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
Ich halte noch an der These fest, dass
Delphi-Quellcode:
LHandle := (FPlugins.Items[i] as ITWPlugin).Handle;
den Referenzzähler hochzählt und zu spät wieder herunterzählt.

:duck:

lizardking 8. Jul 2006 23:16

Re: TInterfaceList und lokale Referenzen
 
Zitat:

Zitat von andreash
Ich halte noch an der These fest, dass
Delphi-Quellcode:
LHandle := (FPlugins.Items[i] as ITWPlugin).Handle;
den Referenzzähler hochzählt und zu spät wieder herunterzählt.

:duck:

Hab's jetzt mal auf Deine Weise ausprobiert und... naja. Funktioniert (wie ich erwartet hab) auch nicht :cry:

lizardking 26. Jul 2006 21:42

Re: TInterfaceList und lokale Referenzen
 
Zitat:

Zitat von andreash
Ich halte noch an der These fest, dass
Delphi-Quellcode:
LHandle := (FPlugins.Items[i] as ITWPlugin).Handle;
den Referenzzähler hochzählt und zu spät wieder herunterzählt.

:duck:

Tada :bounce1:

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:
procedure Foo();
var
  x: ITWPlugin;
begin
  x := FPLugins[0] as ITWPlugin;
  x := nil;
end;
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.

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 04:29 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz