![]() |
[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 ![]() 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:
Diese Funktion wird exportiert und in meinem Hauptprogramm folgendermaßen aufgerufen:
function GetDllInformation: TDllInformation;
begin Result.Author := 'Max Mustermann'; Result.Version := 'v0.2'; Result.Name := 'Standard-Signale'; end;
Delphi-Quellcode:
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?
...
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; Ich nutze Borland Delphi 7 unter Windows XP. Gruß Profiler |
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
|
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?
|
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. |
Re: [DLL]Daten weg nach FreeLibrary
TDllInformation scheint aber ein Record zu sein; dann ist das nicht zu erklären. Hast du ShareMem eingebunden?
|
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:
und wo sollte bei LoadFunction die Exception entstehen?
procedure TDll.UnLoad;
begin {if fDllHandle <> nil then} FreeLibrary(fDllHandle); fDllHandle := nil; end;
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; |
Re: [DLL]Daten weg nach FreeLibrary
Zitat:
@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:
Aber das sind ja nur "Schönheitsfehler" und es löst leider mein eigentliches Problem noch nicht.
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; Gruß Profiler |
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; |
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.
|
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:
In der Struktur waren vorher Strings deklariert, welche ich zu array of Char geändert habe.
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 DLL steht nun:
Delphi-Quellcode:
... und der Zugriff erfolgt so:
procedure GetDllInformation(pInfo: PDllInformation);
begin pInfo^.Author := DLL_AUTHOR; pInfo^.Version := DLL_VERSION; pInfo^.Name := DLL_NAME; end;
Delphi-Quellcode:
Vielen Dank für eure Hilfe.
constructor TDll.Create(FileName: String);
var Func: TFunctionGetDllInformation; begin Inherited Create; fFileName := FileName; fDllHandle := 0; Load; Func := LoadFunction(DLL_GETINFO); Func(fInfo); Unload; end; Gruß Profiler |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:30 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