Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi [DLL]Daten weg nach FreeLibrary (https://www.delphipraxis.net/133007-%5Bdll%5Ddaten-weg-nach-freelibrary.html)

Profiler 23. Apr 2009 18:43


[DLL]Daten weg nach FreeLibrary
 
Hallo,

ich bin mir nicht sicher ob das Thema am besten hierher passt, also schon mal Sorry falls es fehl platziert wurde. Ich beschäftige mich gerade mal wieder mit einer Art Plug-In-System für mein Lüftersteuerungsprogramm PFControl für ThinkPad-Notebooks.
Die jeweiligen DLL's sollen eine Standard-Routine besitzen, dir mir Informationen über sie gibt (Autor, Version, ...). Dabei soll die DLL dynamisch geladen, die Informationen gelesen und im Speicher hinterlegt, und wieder freigegeben werden. In meiner DLL befindet sich also folgende Funktion:

Delphi-Quellcode:
function GetDllInformation: TDllInformation;
begin
  Result.Author := 'Max Mustermann';
  Result.Version := 'v0.2';
  Result.Name := 'Standard-Signale';
end;
Diese Funktion wird exportiert und in meinem Hauptprogramm folgendermaßen aufgerufen:
Delphi-Quellcode:
...
  TFunctionGetDllInformation = function: TDllInformation;
...
    fInfo: TDllInformation;
...
constructor TDll.Create(FileName: String);
var
  Func: TFunctionGetDllInformation;
begin
  Inherited Create;
  fFileName := FileName;
  fDllHandle := 0;
  Load;
  Func := LoadFunction(DLL_GETINFO);
  fInfo := Func;
  Unload;  /* Marke 1 */
  fLoaded := False;  /* Marke 2 */
end;

procedure TDll.Load;
begin
  fDllHandle := LoadLibrary(PChar(fFileName));
  if fDllHandle = 0 then
    raise Exception.Create('"'+fFileName+'" konnte nicht geladen werden!');
  fLoaded := True;
end;

function TDll.LoadFunction(Name: String): Pointer;
begin
  try
    Result := GetProcAddress(fDllHandle, PChar(Name));
  except
    on E: Exception do
      raise Exception.Create('"'+fFileName+'" ist keine gültige Dll für PFControl: '+E.Message);
  end;
end;

procedure TDll.UnLoad;
begin
  if fLoaded then begin
    FreeLibrary(fDllHandle);
    fLoaded := False;
  end;
end;
Zunächst funktioniert alles perfekt bis /* Marke 1 */ im Konstruktor. Wenn die Prozedur Unload noch nicht aufgerufen wurde, stehen in fInfo (Struktur) die gewünschten Daten. Nachdem Unload aufgerufen wurde (/* Marke 2 */), ist fInfo im Debugger nicht mehr lesbar und die Daten sind weg. Wieso bleiben die Daten beim Freigeben der DLL nicht erhalten bzw. wie kann ich es so lösen ohne die DLL dauerhaft im Speicher zu lassen?

Ich nutze Borland Delphi 7 unter Windows XP.

Gruß
Profiler

mkinzler 23. Apr 2009 18:46

Re: [DLL]Daten weg nach FreeLibrary
 
Es handelt sich ja um einen Zeiger auf eine Funktion der Dll. Nach deren Freigabe teigt dieser ins Nirvana

Profiler 23. Apr 2009 19:57

Re: [DLL]Daten weg nach FreeLibrary
 
Naja dass der Zeiger auf die Funktion futsch geht ist ja klar, aber warum gehen die Daten von fInfo verloren? Die Variable hat doch nichts mit der DLL zu tun oder?

Dunkel 23. Apr 2009 20:00

Re: [DLL]Daten weg nach FreeLibrary
 
Weil fInfo ebenfalls nur ein Zeiger ist.
Du musst die Daten, welche Du aus der DLL bekommst, schon in lokale Variablen speichern. Oder, eigentlich besser und auch der Standard von Windows, Du übergibst der DLL einen, im Hauptprogramm alloizierten Speicherbereich, in welchen die DLL die Informationen schreiben kann. Dieser Bereich überlebt auch die DLL.

Apollonius 23. Apr 2009 20:03

Re: [DLL]Daten weg nach FreeLibrary
 
TDllInformation scheint aber ein Record zu sein; dann ist das nicht zu erklären. Hast du ShareMem eingebunden?

himitsu 23. Apr 2009 20:22

Re: [DLL]Daten weg nach FreeLibrary
 
fLoaded kannst'e eigentlich weglassen ... fDllHandle<>0 brächte das selbe Ergebnis
mußt nur das Freigeben noch anpassen
Delphi-Quellcode:
procedure TDll.UnLoad;
begin
  {if fDllHandle <> nil then} FreeLibrary(fDllHandle);
  fDllHandle := nil;
end;
und wo sollte bei LoadFunction die Exception entstehen?
Delphi-Quellcode:
function TDll.LoadFunction(Name: String): Pointer;
begin
  Result := GetProcAddress(fDllHandle, PChar(Name));
  if Result = nil then
    raise Exception.CreateFmt('"%s" ist keine gültige Dll für PFControl', [fFileName]);
end;

Profiler 23. Apr 2009 22:16

Re: [DLL]Daten weg nach FreeLibrary
 
Zitat:

Zitat von Apollonius
TDllInformation scheint aber ein Record zu sein; dann ist das nicht zu erklären. Hast du ShareMem eingebunden?

Ja das ist ein Record, ich weiss grad nicht was mit ShareMem gemeint ist, ich beles mich morgen mal.

@himitsu
Ja das fLoaded hab ich nur der Bequemlichkeit halber eingeführt, was dann über ein Property Loaded: Boolean von der Klasse abgefragt werden kann, aber eigentlich brauch ich das nicht, da das Laden und Freigeben in der Klasse vor und nach einem Prozeduraufruf gesichert werden soll.

Bei der Exception hast du Recht, aber ich möchte erstmal kein Fenster zeigen. Das wird dann von Application.OnException in ein Memo geschrieben bzw. beim Funktionsaufruf in einer höheren Klasse mit abgefangen.

Delphi-Quellcode:
function TDll.LoadFunction(Name: String): Pointer;
begin
  Result := GetProcAddress(fDllHandle, PChar(Name));
  if not Assigned(Result) then
    raise Exception.Create('"'+fFileName+'" ist keine gültige Dll für PFControl: '+Name+' nicht gefunden.');
end;
Aber das sind ja nur "Schönheitsfehler" und es löst leider mein eigentliches Problem noch nicht.

Gruß
Profiler

Blup 24. Apr 2009 08:18

Re: [DLL]Daten weg nach FreeLibrary
 
'Max Mustermann' ist eine String-Konstante, die fest im Speicherbereich der DLL abgelegt ist.

Result.Author := 'Max Mustermann';

Author ist vom Type String, Stringvariablen sind in Wirklichkeit Zeiger auf einen String.
Der Zeiger Author verweist auf den Speicher, in dem die String-Konstante liegt.

Unload;

Der Zeiger Author verweist auf eine Speicheradresse, die nicht mehr von der DLL belegt wird.


Eine mögliche Lösung:
Delphi-Quellcode:
fInfo.Author := Copy(fInfo.Author);
fInfo.Version := Copy(fInfo.Version);
fInfo.Name   := Copy(fInfo.Name);
Unload;

Apollonius 24. Apr 2009 15:42

Re: [DLL]Daten weg nach FreeLibrary
 
Zumindest in den späteren Delphi-Versionen werden von String-Konstanten immer Kopien erstellt. Ich weiß allerdings nicht, wie lange das schon so geht. Es ist allerdings klar, dass es bei Strings Probleme mit dem Speichermanager gibt.

Profiler 25. Apr 2009 21:48

Re: [DLL]Daten weg nach FreeLibrary
 
Hallo,

das mit dem Copy hat mir immer InvalidPointerOperation geworfen.
Ich hab es jetzt aber folgendermaßen gelöst:
Delphi-Quellcode:
type
  PDllInformation = ^TDllInformation;
  TDllInformation = record
    Author: array[0..19] of Char;
    Version: array[0..9] of Char;
    Name: array[0..19] of Char;
  end;
In der Struktur waren vorher Strings deklariert, welche ich zu array of Char geändert habe.
In der DLL steht nun:
Delphi-Quellcode:
procedure GetDllInformation(pInfo: PDllInformation);
begin
  pInfo^.Author := DLL_AUTHOR;
  pInfo^.Version := DLL_VERSION;
  pInfo^.Name := DLL_NAME;
end;
... und der Zugriff erfolgt so:
Delphi-Quellcode:
constructor TDll.Create(FileName: String);
var
  Func: TFunctionGetDllInformation;
begin
  Inherited Create;
  fFileName := FileName;
  fDllHandle := 0;
  Load;
  Func := LoadFunction(DLL_GETINFO);
  Func(fInfo);
  Unload;
end;
Vielen Dank für eure Hilfe.

Gruß
Profiler


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:48 Uhr.
Seite 1 von 2  1 2      

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