Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Probleme beim dynamischen Einbinden einer DLL (https://www.delphipraxis.net/67058-probleme-beim-dynamischen-einbinden-einer-dll.html)

DataCool 8. Apr 2006 22:43


Probleme beim dynamischen Einbinden einer DLL
 
Hi Leute,

irgentwie habe ich gerade ne Denkblockade und seh den Wald vor lauter Bäumen nicht.
Hoffe Ihr könnt mir weiter helfen.
Ich will eine Function aus einer DLL dynamisch laden und ausführen.
Die DLL ist in C++ geschrieben :

Delphi-Quellcode:
In der Dll gibts genau eine Funktion, die da wäre:

int CreateSqlImportScript(
            char *pJournalFile,
            char *pSqlScript,
            int iStandortID,
            int iStammdaten,
            char *pErrorText
            )
(*
Kurze Erklärung:
    pJournal:        StringRef, der den Pfad des Journalfiles angibt.
    pSqlScript:     StringRef, der die Ausgabedatei angibt.
    iStandortID:    StandortID
    iStammdaten: 0 = ohne Stammdaten, 1 = mit
    pErrorText:     StringRef, der eventuell Fehlermeldungen enthält
                          ( Speicher muß alloziert sein ( min. 1014 bytes )
*)
Wenn ich die DLL statisch einbinde funktioniert alles reibungslos.
Jetzt habe ich meine Aktionen bezüglich dieser DLL in eine seperate Klasse ausgelagert(s. Code)

Delphi-Quellcode:
unit VectronImport;

interface

uses Classes, SysUtils;

const

   cDLLName = 'ImpVecEJ.dll';
   cSplit = '|';
   cFilterField : String = '[F]';
   cDateField  : String = '_DT';

   cOk                     = 1;
   cErr_Unknown            = -1;
   cErr_ImportFileNotFound = -2;
   cErr_ImportFileLoadError = -3;
   cErr_DllFileNotFound    = -4;
   cErr_DllLoad            = -5;

 
type

  TImportDll = function (InputFile : PChar; OutputFile : PChar; SOrtID : Integer; Stammdaten : Integer; sError : PChar) : integer; stdcall;

  TOnProgress = procedure(Sender: TObject; const Ready: Byte) of object;

  TVectronImport = Class
    private
      FImpFile      : String;
      FDllDir       : String;
      FstrLFile     : TStringList;
      hDll          : Cardinal;
      FProzReady    : Byte; // 
      fOnProgress   : TOnProgress;
      ImportDll     : TImportDll;
      pRes          : PChar;
      sErr          : String;
     
      function CheckStartConditions : Longint;
    protected
      {}     
    public
      Constructor Create;
      Destructor Destroy; override;

      property ImportFile : String     read FImpFile   write FImpFile;
      property DllDir    : String     read FDllDir    write FDllDir;
      property OnProgress : TOnProgress read fOnProgress write fOnProgress;


      function Start : Longint;
  end;

implementation

uses Windows;

{ TVectronImport }

constructor TVectronImport.Create;
begin
  inherited;
  FImpFile  := '';
  FDllDir   := '';
  hDll      := 0;
  ImportDll := Nil;
  FstrLFile := TStringList.Create;
  FProzReady := 0;
end;

destructor TVectronImport.Destroy;
begin
  if @ImportDll <> Nil then
    @ImportDll := Nil;
  if hDLL <> 0 then begin
    FreeLibrary(hDll);
    hDLL := 0;
  end;
  FreeAndNil(FstrLFile);
  inherited;
end;

function TVectronImport.CheckStartConditions: Longint;
Var sTmp : String;
begin
  if not FileExists(FImpFile) then begin
    result := cErr_ImportFileNotFound;
    exit;
  end;
  sTmp := IncludeTrailingBackslash(FDllDir)+cDLLName;
  if not FileExists(sTmp) then begin
    result := cErr_DllFileNotFound;
    exit;
  end;
  try
    hDll := LoadLibrary(PChar(sTmp));
    if hDll > 0 then begin
      @ImportDll := GetProcAddress(hDll,PChar('CreateSqlImportScript'));
      result := cOk
    end
    else
      Result := cErr_DllLoad;
  except
    Result := cErr_DllLoad;
  end;
end;

function TVectronImport.Start: Longint;
Var iRes : Longint;
begin
  iRes := CheckStartConditions;
  if iRes < cOk then begin
    result := iRes;
    exit;
  end;
  if @ImportDll = nil then exit;
  GetMem(pRes, 1014);
  try
    iRes := ImportDll(pchar(FImpFile),Pchar('d:\dyndll_export.txt'),12,0,pRes);
    sErr := String(pRes);
  finally
    FreeMem(pRes);
    pRes := Nil;
  end;
  result := iRes;
  // jetzt beim verlassen der Unit(Debuggen) kommt eine Schutzverletzung beim Schreiben
end;

end.
Nur zur Vollständigkeit, der Code der die Klasse erzeugt und Start aufruft :
Delphi-Quellcode:
procedure TfrmMain.cmd_TestClick(Sender: TObject);
Var VecImp : TVectronImport;
    iTmp  : Longint;
begin
  VecImp := TVectronImport.Create;
  try
    VecImp.ImportFile := ed_VecExpFile.Text;
    VecImp.DllDir := sAppDir;
    iTmp := VecImp.Start;
  finally
    FreeAndNil(VecImp);
  end;
  showmessage(inttostr(iTmp));
end;
Wie schon als Kommentar in der Function Start erwähnt, tritt beim verlassen der function Start eine Zugriffsverletzung beim Schreiben auf!
Interessant ist :

Lässt man die Zeile "pRes := Nil;" weg, ist die Schutzverletzung an einer gültigen Speicheradresse, mit der Zeile ist die Schutzverletzung bei Adresse 000000000.

Was übersehe ich hier gerade ?

Danke und Gruß

Data

Basilikum 8. Apr 2006 22:55

Re: Probleme beim dynamischen Einbinden einer DLL
 
ersetze mal das
Delphi-Quellcode:
sErr := String(pRes);
durch
Delphi-Quellcode:
sErr := StrPas(pRes);
bei deiner Variante wird wohl der String sErr auf einen Speicherblock zeigen, der kurz darauf freigegeben wird...

DataCool 8. Apr 2006 22:58

Re: Probleme beim dynamischen Einbinden einer DLL
 
Danke, genau das wars. :oops:

:dp:


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:20 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 by Thomas Breitkreuz