Autor Beitrag
Bronstein
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 578
Erhaltene Danke: 1

WIN XP
Delphi 6 / Delphi 2006 / Delphi XE
BeitragVerfasst: So 29.11.09 07:50 
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!

ausblenden volle Höhe 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

_________________
Es gibt keine dummen Fragen nur dumme Antworten!!!
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: So 29.11.09 15:19 
Soweit ich weiss, muss man bei Loadlibrary nur den Namen und nicht den Pfad angeben...
Ausserdem ist sowas:
ausblenden Delphi-Quelltext
1:
2:
3:
if hdll = 0 then
else
...

Absolut schlechter Stil. Besser so:
ausblenden Delphi-Quelltext
1:
2:
if hdll<>0 then
...
Bronstein Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 578
Erhaltene Danke: 1

WIN XP
Delphi 6 / Delphi 2006 / Delphi XE
BeitragVerfasst: So 29.11.09 18:35 
Wenn ich nur den DLL Name angebe bekomme ich den selben Fehler, daran liegt es also auch nicht!
ausblenden Delphi-Quelltext
1:
hDLL := LoadLibrary(DLLName);					

_________________
Es gibt keine dummen Fragen nur dumme Antworten!!!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: 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?