Einzelnen Beitrag anzeigen

Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#28

AW: Übergabe einer Klasse von EXE an DLL

  Alt 26. Nov 2017, 10:16
Ich habe mir mal die Zeit genommen das so aufzubereiten wie ich es für richtig halte.
es geht mir darum zu zeigen wie die Interfaces meiner Meinung nach aussehen sollten.

Zur vereinfachung habe ich mal 2 Deiner Klassen als Basis genommen.
Die Klasse Tmesswert habe ich um einen Info String erweitert.


Mit diesem Ansatz sind im NormalFall so gut wie keine Änderungen in Deinen konkreten Klassen notwendig
und sind komplett Compilerunabhängig. Die Dll kann also auch mit einem anderen Compiler erstellt werden
ohne das Probleme zu erwarten sind.

Delphi-Quellcode:
unit Analyse.Defaults;

interface
  uses classes, Generics.collections;
 // Hier nur zur verdeutlichung
 type
  TMesswert = class(TObject)
    Belastung : Real;
    Strom : Real;
    Info : String;
  end;

  TMesswertListe = class( TObjectList<TMesswert> )
  end;

implementation
end.
Als nächstes die Interfaces dazu:

Delphi-Quellcode:
unit Analyse.Interfaces;
interface
 type
    IMesswert = interface
   ['{CAD5EAF6-D0DE-4C2A-A955-EEDE805B09F4}']
      function GetBelastung: Double; stdcall;
      function GetInfo: WideString; stdcall;
      function GetStrom: Double; stdcall;
      procedure SetBelastung(const Value: Double); stdcall;
      procedure SetInfo(const Value: WideString); stdcall;
      procedure SetStrom(const Value: Double); stdcall;
      property Belastung: Double read GetBelastung write SetBelastung;
      property Info: WideString read GetInfo write SetInfo; // WideString wird verwendet weil da Windows das Speicherhandling übernimmt
      property Strom: Double read GetStrom write SetStrom;

   end;

  // Hier kommt alles rein was der Konsument können muss
   IMesswertList = interface
      ['{A8F39543-4F57-49EB-99B8-78DD4DBCA4B9}']
      // Wir wollen wissen wieviele Einträge es gibt...
      function GetCount: Integer; stdcall;
      // Nur LeseZugriff auf die Items
      function GetItem( index : Integer) : IMesswert; stdcall;
      // Abfragen eines Index
      function GetItemIndex(item : IMesswert) : integer; stdcall;
      // Neuen Eintrag anhängen
      function AddItem : IMesswert; stdcall;
   end;
implementation
end.
Hier die Implementierung

Delphi-Quellcode:
unit Analyse.Implementations;

interface
uses
   System.sysutils,
   System.classes,
   Analyse.Interfaces,
   Analyse.Defaults;

// Hier definieren wir 2 Wrapper Kalssen für die Interfaces

type
  TIMesswert = class(TInterfacedObject, IMesswert)
   private
    FMesswert : TMesswert;
    function GetBelastung: Double; stdcall;
    function GetInfo: WideString; stdcall;
    function GetStrom: Double; stdcall;
    procedure SetBelastung(const Value: Double); stdcall;
    procedure SetInfo(const Value: WideString); stdcall;
    procedure SetStrom(const Value: Double); stdcall;
   protected
     function getMesswert : TMesswert;
   public
    constructor Create(aMesswert : TMesswert);
    destructor Destroy; override;
  end;


  TIMesswertListWrapper = class(TInterfacedObject, IMesswertList)
   private
     Flist : TMesswertListe;
     function AddItem: IMesswert; stdcall;
     function GetCount: Integer; stdcall;
     function GetItem(index : Integer): IMesswert; stdcall;
     function GetItemIndex( item : IMesswert): integer; stdcall;
   public
    constructor Create(const aList : TMesswertListe );
    destructor Destroy; override;
  end;

implementation

function TIMesswert.GetBelastung: Double;
begin
   Result := FMesswert.Belastung;
end;

function TIMesswert.GetStrom: Double;
begin
   Result := FMesswert.Strom;
end;

procedure TIMesswert.SetBelastung(const Value: Double);
begin
   Fmesswert.Belastung := Value;
end;

procedure TIMesswert.SetStrom(const Value: Double);
begin
   FMesswert.Strom := Value;
end;

function TIMesswert.getMesswert: TMesswert;
begin
  result := FMesswert;
end;

constructor TIMesswert.Create(aMesswert: TMesswert);
begin
  inherited create;
  FMesswert := aMesswert;
end;

destructor TIMesswert.Destroy;
begin
  FMesswert := nil;
  inherited;
end;

function TIMesswert.GetInfo: WideString;
begin
  result := FMesswert.Info;
end;

procedure TIMesswert.SetInfo(const Value: WideString);
begin
  FMesswert.Info := Value;
end;

{ TIMesswertListWrapper }

constructor TIMesswertListWrapper.Create(const aList: TMesswertListe);
begin
  inherited Create;
  Assert(Flist = nil,'Liste muss übergeben werden');
  Flist := aList;
end;

destructor TIMesswertListWrapper.Destroy;
begin
  flist := nil;
  inherited;
end;

function TIMesswertListWrapper.AddItem: IMesswert;
var lMesswert : TMesswert;
begin
  lMesswert := TMesswert.create;
  Flist.add(lMesswert);
  result := TIMesswert.Create(lMesswert);
end;

function TIMesswertListWrapper.GetCount: Integer;
begin
  result := Flist.count;
end;

function TIMesswertListWrapper.GetItem(index : Integer): IMesswert;
begin
   // TODO -cMM: index prüfen
   result := TIMesswert.Create(flist[index]);
end;

function TIMesswertListWrapper.GetItemIndex(item : IMesswert): integer;
begin
// TODO -cMM: Gültigkeit von item prüfen
   result := Flist.IndexOf((item as TIMesswert).getmesswert);
end;

end.
Und nun zur Benutzung

Delphi-Quellcode:
unit Analyse.Worker;

interface

uses
  Analyse.Defaults;
  type
    tAnalyseWork = class
       public
         class function doAnalyse(aList : TMesswertListe) : boolean;
    end;

implementation

uses
  Analyse.Interfaces,
  Analyse.Implementations;

 // Nur als Dummy hier
  function DllFunc(List : IMesswertList) : boolean; stdcall; // external whatever
  begin
     result := false;
  end;

{ tAnalyseWork }
class function tAnalyseWork.doAnalyse(aList: TMesswertListe): boolean;
var lWorker : TIMesswertListWrapper;
begin
  lworker := TIMesswertListWrapper.Create(Alist);
  try
      // Aufruf der Dll
     result := Dllfunc(lworker);
  finally
     lworker := nil;
  end;
end;
end.
Fritz Westermann
  Mit Zitat antworten Zitat