Entwickler-Ecke

Dateizugriff - dynamisches einbinden einer DLL Fehler, List Index out of...


Bronstein - So 29.11.09 07:50
Titel: dynamisches einbinden einer DLL Fehler, List Index out of...
Hallo,
ich habe ein Problem beim dynamischen einbinden einer DLL.
Bekomme immer den Fehler:
Project Project1.exe raised exception class EStringListError with message 'List index out of bounds (-1)'. Process stopped. Use Step or Run to continue.
Und zwar in der Funktion "GetUmruestDauer" in der Zeile 89 "XML := FarProc(pChar(tmpVon), pChar(tmpNach));"

Wie man bei der Funktion "GetUmruestDauer" in der Zeile 75 sieht, rufe ich die Funktion auch mal auf wo ich die DLL fest eingebunden habe, doch da bekomme ich keinen Fehler.
Deshalb liegt es ja nicht an der DLL, was mache ich beim dynamischen einbinden aber falsch?

Das dynamische einbinden der Funktion "GetRuestungPfad" funktioniert doch auch (Zeile 49) und bei "GetUmruestDauer" mache ich doch nichts anderes!


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ActiveX, XMLDOC, XMLIntf;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

function DLL_GetUmruestung(RuestungVon, RuestungNach: Pchar): PChar; stdcallexternal 'test.dll' name 'GetUmruestung';

{$R *.dfm}

function GetPfadRuestung(DLLName, Linie, Ruestung: String): PChar;
type
  TGetRuestungPfad = function(Linie, Ruestung: Pchar): PChar;
var
  hDLL: THandle; // Handle zur DLL
  iRes: integer; // Ergebnis der Funktion
  FarProc: TGetRuestungPfad;
  sDLLPath, XML: PChar;
  xmlDocTaktZeit: IXmlDocument;
  tmpStr: String;
begin
  sDLLPath := pChar(ExtractFilePath(ParamStr(0)) + ''+DLLName);
  hDLL := LoadLibrary(sDLLPath);
  if hDLL = 0 then

  else
  begin
    try
      FarProc := GetProcAddress(hDLL, 'GetRuestungPfad');
      if Assigned(FarProc) then
      begin
        //CoInitialize(nil);
        XML := FarProc(pChar(Linie), pChar(Ruestung));
        xmlDocTaktZeit := LoadXMLData(XML);
        tmpStr := xmlDocTaktZeit.DocumentElement.ChildNodes['Ruestung'].NodeValue + '\';
        result := PChar(tmpStr);
      end;
    except

    end;
  end;
  FreeLibrary(hDLL);
end;

function GetUmruestDauer(DLLName, Linie, RuestungVon, RuestungNach: PChar): Integer;
type
  TGetUmruestung = function(RuestungVon, RuestungNach: Pchar): PChar;
var
  hDLL: THandle; // Handle zur DLL
  iRes: integer; // Ergebnis der Funktion
  FarProc: TGetUmruestung;
  sDLLPath, XML, tmpStr: PChar;
  xmlDocTaktZeit: IXmlDocument;
  tmpVon, tmpNach: String;
begin
  CoInitialize(nil);
  tmpVon := GetPfadRuestung(DLLName, Linie, RuestungVon);
  tmpNach := GetPfadRuestung(DLLName, Linie, RuestungNach);
  XML := DLL_GetUmruestung(pChar(tmpVon), pChar(tmpNach));
  ShowMessage(XML);

  sDLLPath := pChar(ExtractFilePath(ParamStr(0)) + ''+DLLName);
  hDLL := LoadLibrary(sDLLPath);
  if hDLL = 0 then

  else
  begin
    try
      FarProc := GetProcAddress(hDLL, 'GetUmruestung');
      if Assigned(FarProc) then
      begin
        CoInitialize(nil);
        XML := FarProc(pChar(tmpVon), pChar(tmpNach));

        xmlDocTaktZeit := LoadXMLData(XML);
        ShowMessage(XML);
      end;
    except

    end;
  end;
  FreeLibrary(hDLL);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  DLLName: String;
begin
  DLLName := 'test.dll';
  GetUmruestDauer(Pchar(DllName), pChar('Linie_1'), pChar('B_980_050_1'), pChar('B_980_050_2'));
end;

end.



Moderiert von user profile iconNarses: Topic aus VCL (Visual Component Library) verschoben am So 29.11.2009 um 12:39


Boldar - So 29.11.09 15:19

Soweit ich weiss, muss man bei Loadlibrary nur den Namen und nicht den Pfad angeben...
Ausserdem ist sowas:

Delphi-Quelltext
1:
2:
3:
if hdll = 0 then
else
...

Absolut schlechter Stil. Besser so:

Delphi-Quelltext
1:
2:
if hdll<>0 then
...


Bronstein - So 29.11.09 18:35

Wenn ich nur den DLL Name angebe bekomme ich den selben Fehler, daran liegt es also auch nicht!

Delphi-Quelltext
1:
hDLL := LoadLibrary(DLLName);                    


jaenicke - So 29.11.09 18:49

Der Unterschied ist, dass du stdcall nicht bei der Deklaration angegeben hast. Dementsprechend werden die Parameter auch entsprechend anders übergeben, so dass das nicht zusammenpasst, wenn in der DLL diese Konvention angegeben ist.

Generell: Ist die DLL auch von dir? Dann debugge die doch einfach, denn da du in dem geposteten Quelltext keine TStringList benutzt, muss der Fehler ja innerhalb der DLL auftreten.


Delete - So 29.11.09 19:05

user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:
Soweit ich weiss, muss man bei Loadlibrary nur den Namen und nicht den Pfad angeben...

Aha. Und woher weiß der Loader dann wo er die DLL findet?`:roll:


Boldar - So 29.11.09 21:37

Weil er erst im Windows-Verzeichnis sucht, dann im %path% und dann im Arbeitsverzeichnis (dachte ich bisher). Bei der statischen Einbindung ist das doch auch so, und ich wollte auch immer schon bei meinen Projecten die dll's in Unterordner packen, aber das hat nie funktioniert.
Aber wenn du das so sagst, war mein Fehler bestimmt wo anders...


jaenicke - So 29.11.09 22:31

Ich habe schon öfter die DLLs in Unterverzeichnisse gelegt, wie bei anderen Programmen ja auch. Insbesondere bei meinem größten Projekt mit ca. 50 DLLs wäre das sonst sehr unübersichtlich geworden.

Was die Suche angeht hast du wohl Recht, aber das Arbeitsverzeichnis ist ja nicht unbedingt das der Exe, insofern bringt das wenig.


Delete - So 29.11.09 23:41

user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:
Weil er erst im Windows-Verzeichnis sucht, dann im %path% und dann im Arbeitsverzeichnis (dachte ich bisher).

Und wenn ich die DLL in eine Unterverzeichnis des Programms lege? Und das Arbeitsverzeichnis kann irgend ein verzeichnis sein, aber nicht unbedingt das Programmverzeichnis. Und was ist, wenn es mehrere DLLs mit gleichen Namen gibt?