Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Datenaustausch zw. DLL und Applikation (https://www.delphipraxis.net/77512-datenaustausch-zw-dll-und-applikation.html)

RuX 20. Sep 2006 15:59


Datenaustausch zw. DLL und Applikation
 
Abstrakte Frage:
Was ist der beste Weg um zw. einer D3 App und einer D7 dll kompatibel Daten (Liste von Records) zu übertragen?

Konkretes Problem:
Eine Anwendung die mit Delphi 3 geschrieben ist braucht spezielle Daten die per Web-Service abrufbar sind. Da Web-Services mit Delphi3 nicht "nativ" möglich sind (gibs dafür überhaupt was!? egal) will ich mit D7 eine dll schreiben die die Daten des Web-Services abfragt.
Ich möchte eine Struktur kompatibel zw. der D7 DLL und der D3 exe übertragen.
Es handelt sich um eine simple Liste von Records die ich auf D3 Seite instanziiere und per var Parameter and die dll weitergebe die sie mir dann befüllt.
Die Listen-Klasse hab ich selbst geschrieben (ne einfache verkettete Liste) da TList und alles vorhandene nicht kompatibel zw. den Delphi Versionen ist.
Der Record ist auch sehr einfach, ein paar einfache Integers und Strings. SizeOf liefert auf beiden Seiten das gleiche Ergebnis. Der Record wird auf Dll Seite allokiert und dann in die Liste eingehängt.
Beide Units die von D7 und D3 verwendet werden (Liste und Definition vom Record) lassen sich in beiden problemlos kompilieren.
Trotzdem gibt es beim freigeben der Liste (D3 Seite, nach der Datenübertragung die sogar klappt!) eine Exception (und dann noch n paar mehr :P).
Da das jetzt schon so gut funktioniert hat Frage ich mich woran das liegen könnte. Debuggen ist Schwer. Entweder es geht nur D3 oder D7 :/

Eine andere Möglichkeit zum Datenübertragen die mir einfällt wäre File I/O aber das würde ich gern vermeiden.

Hier mal die Liste

Delphi-Quellcode:
unit LinkList;

interface

type
  PLinkListItem = ^TLinkListItem;
  TLinkListItem = record
    Next: PLinkListItem;
    Data: Pointer;
  end;

  TLinkList = class
  private
    FAnchor: PLinkListItem;
    function GetItem(AIndex: Integer): PLinkListItem;
    function GetItemData(AIndex: Integer): Pointer;
  public
    constructor Create;
    destructor Destroy; override;

    property Items[Index: Integer]: Pointer read GetItemData; default;
    procedure Add(AItem: Pointer);
    procedure Clear;
    function Count: Integer;
  end;

implementation

{ LinkList }

constructor TLinkList.Create;
begin
  inherited;
  FAnchor := nil;
end;

destructor TLinkList.Destroy;
begin
  Clear;
  inherited;
end;

procedure TLinkList.Add(AItem: Pointer);
var ANewItem: PLinkListItem;
begin
  New(ANewItem);
  ANewItem^.Data := AItem;
  ANewItem^.Next := nil;
  if not Assigned(FAnchor) then
    FAnchor := ANewItem
  else
    GetItem(Count-1)^.Next := ANewItem;
end;

function TLinkList.Count: Integer;
var AItem: PLinkListItem;
begin
  result := 0;
  AItem := FAnchor;
  while Assigned(AItem) do begin
    Inc(result);
    AItem := AItem.Next;
  end;
end;

function TLinkList.GetItem(AIndex: Integer): PLinkListItem;
var CurrIdx: Integer;
begin
  result := FAnchor;
  CurrIdx := 0;
  while Assigned(result) AND (CurrIdx < AIndex) do begin
    Inc(CurrIdx);
    result := TLinkListItem(result^).Next;
  end;

  if (CurrIdx <> AIndex) OR (not Assigned(result)) then
    result := nil;
end;

function TLinkList.GetItemData(AIndex: Integer): Pointer;
begin
  result := GetItem(AIndex);
  if Assigned(result) then
    result := TLinkListItem(result^).Data;
end;

procedure TLinkList.Clear;
var ANext, AItem: PLinkListItem;
begin
  AItem := FAnchor;
  while Assigned(AItem) do begin
    ANext := AItem^.Next;
    Dispose(AItem);
    AItem := ANext;
  end;
end;

DGL-luke 20. Sep 2006 16:17

Re: Datenaustausch zw. DLL und Applikation
 
Was verhindert, dass du dein D3-Projekt auf D7 migrierst?

RuX 20. Sep 2006 16:19

Re: Datenaustausch zw. DLL und Applikation
 
bde, 1000000 zeilen, inkompatibilitäten, fehlende klassen,... das thema steht nicht zur debatte

Elvis 20. Sep 2006 16:33

Re: Datenaustausch zw. DLL und Applikation
 
Den Record als packed record und die Liste als Interface sollten es dir ermöglichen den gleichen Code (für Record, Classe und Interface) in beiden Delphi versionen zu benutzen. Da Delphi-Interfaces immer COM-interfaces[1] sind und packed Records keine Alignment-Ärgereien machen dürften[2], würde ich davon ausgehen, dass du sie einfach in exportierten Funktionen der DLL ein- und ausgeben kannst.

[1]müssen gleich sein, da sich an COM seit damals wohl nix geändert hat ;)
[2]müssen auch kompatibel sein, da das nunmal der Weg ist um Strukturen an non-Delphi-Sprachen zu übergeben.

RuX 20. Sep 2006 16:47

Re: Datenaustausch zw. DLL und Applikation
 
nur zum verständnis:
ich definier die liste als interface und implementier dann die funktionen jeweils auf d3/d7 seite (eigentlich sollte ja auch wieder der gleiche code gehn). und als mein var listen-parameter übergeb ich die instanz die das interface implementiert?

das mit den packed records wusst ich zwar eigentlich, hatte's aber nicht gemacht :wall: :P

werd ich mal probieren danke für den tipps!

RuX 22. Sep 2006 14:14

Re: Datenaustausch zw. DLL und Applikation
 
:( Also es funktioniert leider nicht wie ichs jetzt probier habe:

mit den methoden der obigen liste hab ich ein interface deklariert (ILinkList)
die liste (TLinkList) erbt dann von ILinkList und gezwungener maßen von TInterfacedObject
als dll funktion parameter übergeb ich ein pointer auf eine TLinkList (PLinkList = ^TLinkList)

hatte ich das so richtig verstanden elvis?

die adresse vom parameter ist auch auf beiden seiten identisch aber schon der anchor ist dann unterschiedlich :(

die delaration der funktion schaut so aus (beide seiten ;))

Delphi-Quellcode:
procedure GetStruct(ALinkList: PLinkList); stdcall;
aufruf d3 seite
Delphi-Quellcode:
var AStruct: TLinkList
begin
  AStruct := TLinkList.Create;
  try
    GetStruct(PLinkList(@AStruct));
    ...irgendwas mit den daten machen...
  finally
    AStruct.free;
  end;
end;
verarbeitung dll/d7
Delphi-Quellcode:
procedure GetStruct(ALinkList: PLinkList); stdcall;
begin
  if Assigned(ALinkList) then begin
    ALinkList^.Clear;
    ALinkList^.Add(NewElement);
    ...
  end;
end;
was mach ich falsch? :|

Bernhard Geyer 22. Sep 2006 19:33

Re: Datenaustausch zw. DLL und Applikation
 
Zitat:

Zitat von Elvis
Da Delphi-Interfaces immer COM-interfaces[1] sind ....

Stimmt nicht. Man kann in Delphi Interfaces nach Lust und laune verwenden ohne das man mit COM von Windows zu tun hat. Es stimmt aber das die Delphi-Interfaces zu ausgelegt sind das sie mit COM harmonisch agieren. (Wer COM-Interfaces mit C++ verwendet weis was ich meine). Also kann Borland hier sehrwohl im hintergrund änderungen vornehmen.
Deshalb deshalb glaube ich nicht das es erlaubt ist zwischen unterschiedlichen Delphi-Versionen interfaces zwischen Exe und DLL auszutauchen. Ich denke hier gibt es die gleichen Probleme wie mit "richtigen" Referenzen.

Wenn Du unterschiedliche Versionen von Delphi in Exe und DLL einsetzen willst bleibt dir nichts übrig als nur das zu nehmen was jede andere nicht Delphi-Sprache auch versteht. Eine C-Kompatible schnittstelle. Und wie du schon geschrieben hast willst Du auch Strings übertragen. Und da wird es krachen. Du wirst auf PChar's umsteigen müssen damit es klappt (Ich glaube nicht das Sharemem von D3 (gab das damals schon?) mit Sharemem von D7 kompatible ist.

SirThornberry 22. Sep 2006 20:24

Re: Datenaustausch zw. DLL und Applikation
 
Delphi3-Objecte sind inkompatibel zu Delphi7-Objecten. Von daher geht es nicht das du eine in Delphi3 erzeugte TLinklist mit Delphi7 befüllst.

RuX 25. Sep 2006 08:11

Re: Datenaustausch zw. DLL und Applikation
 
ja scheint wohl leider so zu sein.
ich hab ja auch kein problem damit pchars zu verwenden bloß diese relativ komplexen strukturen alle innerhalb von einem oder mehreren pchars zu übertragen gefällt mir nicht :|
dann werd ich wohl doch mal mit file i/o experementieren.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:58 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz