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.