Hallo!
Ich komm grad bei der Übergabe eines Records an eine
DLL-Procedure nicht weiter. Der Record enthält eine Widestring-Variable, welche leer an die
DLL übergeben wird, dort geschrieben werden soll und dann innerhalb der Anwendung weiter verarbeitet.
Mein Textcode funktioniert so lange wie ich die dynamisch geladene
DLL per FreeLibrary wieder entlade. Dann gibt der Speichermanager alles frei was innerhalb der
DLL existiert hat und ich bekomme logischerweise in der Anwendung eine
AV. Kommentiere ich das FreeLibrary einfach aus funktioniert es wunderbar. Was mich da stutzig macht: Ich bekomme trotz FastMM4 beim Schließen der Anwendung keine Memleaks angezeigt, obwohl die
DLL nicht richtig entladen wurde.
Wobei mir wichtiger ist zu verstehen, wie man Widestrings richtigerweise mit DLLs austauscht und die Inhalte der Widestrings über das FreeLibrary hinaus "konserviert". Hier mein Testcode:
Delphi-Quellcode:
// === Die DLL ===
library MyDLL;
uses
FastMM4,
System.SysUtils,
System.Classes,
ModuleInfo
in '
..\..\Common\ModuleInfo.pas';
{$R *.res}
procedure GetModuleInfo(AModuleInfo: PModuleInfo);
stdcall;
const
MODULENAME:
String = '
My DLL';
begin
if AModuleInfo <>
NIL then begin
AModuleInfo^.ModuleName:= MODULENAME;
end;
end;
exports GetModuleInfo;
begin
end.
// === ModuleInfo.pas ===
unit ModuleInfo;
interface
uses
Windows, SysUtils;
type
TModuleInfo =
record
ModuleName:
String;
end;
PModuleInfo = ^TModuleInfo;
TModuleInfoProc =
procedure (AModuleInfo: PModuleInfo);
stdcall;
function GetModuleInfo(
const AModuleFile: TFileName; AModuleInfo: pModuleInfo): Boolean;
implementation
function GetModuleInfo(
const AModuleFile: TFileName; AModuleInfo: PModuleInfo): Boolean;
var
hDLL: THandle;
hProc: TModuleInfoProc;
begin
result:= FALSE;
hDLL:= SafeLoadLibrary(AModuleFile);
if hDLL <> 0
then begin
@hProc:= GetProcAddress(hDLL, '
GetModuleInfo');
if Assigned(hProc)
then begin
hProc(AModuleInfo);
result:= TRUE;
end;
// FreeLibrary(hDLL); <-- Die magische Zeile ;-)
end;
end;
end.
// === Die Hostanwendung ===
procedure TForm1.Button1Click(Sender: TObject);
var
MI: TModuleInfo;
Path: TFileName;
begin
Path:= IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) + '
Modules\MyDLL.dll';
if GetModuleInfo(Path, @MI)
then begin
Label1.Caption:= MI.ModuleName;
// <-- Mit FreeLibrary gibts hier die AV
end;
end;