Entwickler-Ecke

Sonstiges (Delphi) - TList aus DLL


AXMD - Di 07.12.04 23:34
Titel: TList aus DLL
Hi!

Ich habe eine Funktion in einer DLL, die folgendermaßen aussieht:


Delphi-Quelltext
1:
function GetLoggedUsers: TStringList; export;                    


Meine Frage: ist eine Funktion dieser Art überhaupt möglich und wenn ja: was muss ich dabei beachten (hab schon sharemem im uses hinzugefügt)? Hab die DLL noch nicht getestet, da ich sie zuerst fertigschreiben will.

AXMD


AndyB - Mi 08.12.04 00:14
Titel: Re: TList aus DLL
AXMD hat folgendes geschrieben:
Meine Frage: ist eine Funktion dieser Art überhaupt möglich

Kompilieren tut der Compiler sie zumindest mal.

Zitat:
hab schon sharemem im uses hinzugefügt

Als aller erste Unit in der .dpr Datei? Und das nicht nur in der DLL .dpr sondern auch in der EXE .dpr.


AXMD - Mi 08.12.04 00:16

Dass sie der Compiler kompiliert ist klar; und dass ich sharemem im Projekt, das die DLL aufruft ist auch klar. Vielleicht sollt ich mal meine Frage etwas umformulieren: funktioniert die Übergabe eines Objekts wie einer TStringList auch zur Laufzeit problemlos?

AXMD


AndyB - Mi 08.12.04 01:04

Mit ShareMem sollte das kein Problem darstellen. Wobei ich bei Delphi eher zu den Packages neige, da ich mich da um gar nichts mehr kümmern muss, weil der Compiler schon alles notwendige veranlasst.


AXMD - Mi 08.12.04 10:47

Muss ich bei der Verwendung von sharemem irgendetwas beachten, d.h. mit dem Programm mitliefern? Bin in der Materie DLL-Programmierung noch nicht so firm, weil ich mich erst seit kurzem damit beschäftige. Und ich möchte zwischen einem Programm und einer DLL Datentypen wie Strings, TStringLists etc. hin- und hertransferieren.

AXMD


AXMD - Fr 10.12.04 23:32
Titel: Funzt nicht
Hm... es funzt nicht wirklich. Oder ich sags besser so: es funktioniert wunderbar, aber wenn ich die EXE schließe erhalte ich haufenweise EInvalidPointer-Fehler. Hier mal der Code, den ich zum Testn verwendet habe:

DLL:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
library bla;

uses
  Classes,
  sharemem;

{$R *.res}

function GetIt: TStringList;
begin
  Result := TStringList.Create;
  Result.Add('123');
  Result.Add('456');
  Result.Add('Blub');
end;

exports
  GetIt;

end.


EXE:


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:
unit Unit1;

interface

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

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

function GetIt: TStringList; external 'bla.dll';

var
  Form1: TForm1;

implementation

uses sharemem;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  s: TStringList;
  i: Integer;
begin
  s := GetIt;
  for i := 0 to s.Count - 1 do
    ShowMessage(s[i]);
  s.Free;
end;

end.


wulfskin - Sa 11.12.04 01:04

Hallo AXMD,

erstens musst du ShareMem als erste Unit einbinden. Bei dir im Quelltext ist das nicht der Fall. Zweitens würde ich die StringList als Parameter einer Prozedur übergeben und nicht in der DLL erstellen. Drittens würde ich empfehlen hinter den Methode die Aufrufkonvention stdcall zu verwenden, damit die DLL auch von anderen Programmiersprachen einfach angesprochen werden kann.
Sonst sehe ich eigentlich keine Fehler.

Gruß Hape!


AXMD - Sa 11.12.04 12:42

stdcall ist nicht notwendig, da die DLLs gar nicht anderwertig genutzt werden sollen. Mein Problem besteht allerdings immer noch. Hier der Code:

Dummy-App:


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:
unit Unit1;

interface

uses
  sharemem, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

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

procedure GetIt(var List: TStringList); external 'bla.dll';

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  s: TStringList;
  i: Integer;
begin
  s := TStringList.Create;
  GetIt(s);
  for i := 0 to s.Count - 1 do
    ShowMessage(s[i]);
  s.Free;
end;

end.


Und die DLL:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
library bla;

uses
  sharemem,
  Classes;

{$R *.res}

procedure GetIt(var List: TStringList);
begin
  List.Add('123');
  List.Add('456');
  List.Add('Blub');
end;

exports
  GetIt;

end.


Ich bekomm noch immer eine EInvalidPointer-Exception, wenn ich die Form schließe :?

AXMD


Sprint - Sa 11.12.04 13:55

Ich weiß zwar nicht warum du dir das unbedingt antun willst (ShareMem).

Setze in in deinem DLL Projekt ShareMem als erste Position bei Uses.


Delphi-Quelltext
1:
2:
uses
  Sharemem, SysUtils, Classes;



Und bei deinem EXE Projekt auch.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
program Project1;

uses
  ShareMem,
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.



Und dann entferne das var in der Prozedur.