Einzelnen Beitrag anzeigen

Benutzerbild von DataCool
DataCool

Registriert seit: 10. Feb 2003
Ort: Lingen
909 Beiträge
 
Delphi 10.3 Rio
 
#1

Probleme beim dynamischen Einbinden einer DLL

  Alt 8. Apr 2006, 22:43
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
Der Horizont vieler Menschen ist ein Kreis mit Radius Null, und das nennen sie ihren Standpunkt.
  Mit Zitat antworten Zitat