Einzelnen Beitrag anzeigen

Benutzerbild von Codehunter
Codehunter

Registriert seit: 3. Jun 2003
Ort: Thüringen
2.272 Beiträge
 
Delphi 10.4 Sydney
 
#1

Record mit Widestring am DLL übergeben bei XE2

  Alt 2. Jul 2013, 13:34
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;
Ich mache grundsätzlich keine Screenshots. Schießen auf Bildschirme gibt nämlich hässliche Pixelfehler und schadet der Gesundheit vom Kollegen gegenüber. I und E zu vertauschen hätte den selben negativen Effekt, würde aber eher dem Betriebsklima schaden

Geändert von Codehunter ( 2. Jul 2013 um 13:36 Uhr)
  Mit Zitat antworten Zitat