Thema: Delphi DLL Integration kürzen

Einzelnen Beitrag anzeigen

Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#15

Re: DLL Integration kürzen

  Alt 14. Okt 2007, 10:49
Quick&Dirty will wohl seinem Namen alle Ehre machen, hmm?

@Alf, Probleme kommen ganz einfach.
Du hast eine exportierte Funktion, die eine Referenz vom Typ TStrings nimmt und übergibst ihr natürlich eine Ableitung.
Hier kann es ganz schnell fies werden, da die übergebene Referenz ihre Methoden auf einer VMT abbildet, die nicht mit denen der DLL-Version dieser Klasse übereinstimmen.
Kurz: Du musst die gleiche Version der benutzten Units haben und die gleiche Version des Compilers. Ergo: Man landet wieder bei Packages, nur ohne die Sicherheit und Einfachheit, die Packages mitbringen.
Ein "passt scho'" akzeptiere ich hier nicht.
Da kann man gleich VB'ler werden, bei den Honks wäre das eine akzeptable Einstellung, aber deshalb sind diese Honks auch nur VB'ler und keine Entwickler.

Ich predige hier schon lange wiederholt eine einfache und sehr elegante Möglichkeit um Objekte in DLLs benutzen zu können, ohne sich sinnlos an eine RTL- oder Delphiversion zu fesseln: Interfaces.
Man kann sich eine einfache Verpackung für einebestehende TSTrings-Referenz bauen, die man problemlos als Interface an eine Delphi/FPC- -DLL schicken kann (auch C++, wenn WideString anstatt AnsiString benutzt wird).

Delphi-Quellcode:
type
  ISharedStringList = interface
  ['{3F5E3362-121A-4EC4-B399-9F8CD321FC34}']
    procedure Clear; stdcall;
    function GetCount : Integer; stdcall;

    function Add(const aValue : String) : Integer; stdcall;
    procedure Delete(aIndex : Integer); stdcall;
    procedure Exchange(aIndex1, aIndex2 : Integer); stdcall;
    function IndexOf(const aValue : string) : Integer; stdcall;
    procedure Insert(aIndex : Integer; const aValue : string); stdcall;

    function GetItem(aIndex : Integer) : String; stdcall;
    procedure SetItem(aIndex : Integer; const aValue : String); stdcall;

    property Item[aIndex : Integer] : String
      read GetItem
      write SetItem; default;
  end;
Delphi-Quellcode:
uses
  Classes,
  uSharedInterface;

type
  TSharedStringListWrapper = class(TInterfacedObject, ISharedStringList)
  private
    fInnerList: TStrings;
  protected
    function GetCount: Integer; stdcall;

    procedure Clear; stdcall;

    function Add(const aValue: String): Integer; stdcall;
    procedure Delete(aIndex : Integer); stdcall;
    procedure Exchange(aIndex1, aIndex2 : Integer); stdcall;
    function IndexOf(const aValue : String) : Integer; stdcall;
    procedure Insert(aIndex : Integer; const aValue : String); stdcall;

    function GetItem(aIndex: Integer): String; stdcall;
    procedure SetItem(aIndex: Integer; const aValue: String); stdcall;
  public
    property InnerList : TStrings read fInnerList;

    constructor Create(aInnerList : TStrings);

    class function Wrap(aInnerList : TStrings) : ISharedStringList;
  end;
implementation

{ TSharedStringListWrapper }

function TSharedStringListWrapper.Add(const aValue : String) : Integer;
begin
  result := InnerList.Add(aValue);
end;

procedure TSharedStringListWrapper.Clear;
begin
  InnerList.Clear();
end;

constructor TSharedStringListWrapper.Create(aInnerList : TStrings);
begin
  inherited Create();
  fInnerList := aInnerList;
end;

procedure TSharedStringListWrapper.Delete(aIndex : Integer);
begin
  InnerList.Delete(aIndex);
end;

procedure TSharedStringListWrapper.Exchange(aIndex1, aIndex2 : Integer);
begin
  InnerList.Exchange(aIndex1, aIndex2);
end;

function TSharedStringListWrapper.GetCount : Integer;
begin
  result := InnerList.Count;
end;

function TSharedStringListWrapper.GetItem(aIndex : Integer) : String;
begin
  result := InnerList[aIndex];
end;

function TSharedStringListWrapper.IndexOf(const aValue : String) : Integer;
begin
  result := InnerList.IndexOf(aValue);
end;

procedure TSharedStringListWrapper.Insert(aIndex : Integer;
  const aValue : String);
begin
  InnerList.Insert(aIndex, aValue);
end;

procedure TSharedStringListWrapper.SetItem(aIndex : Integer;
  const aValue : String);
begin
  InnerList[aIndex] := aValue;
end;

class function TSharedStringListWrapper.Wrap(aInnerList : TStrings) : ISharedStringList;
begin
  result := Create(aInnerList);
end;
Delphi-Quellcode:
uses
  ShareMem,
  uSharedInterface in '..\uSharedInterface.pas';

{$R *.res}

procedure AddToStringList(const aStringList : ISharedStringList; const aString : String); stdcall;
begin
  aStringList.Add(aString);
end;

exports
  AddToStringList;
Die kann man nun immer nehmen, wenn man irgendeine TStrings-Ableitung in einer DLL bearbeiten will.
Miniaturansicht angehängter Grafiken
screenie_1_469.png  
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat