Also ich hab das ganze über ne Klasse gelöst, die den Zugriff auf die Liste über interfaces kapselt. Um möglichst kompatibel mit verschiedenen Datentypen zu sein hab ich mir zuerst nen record definiert:
Delphi-Quellcode:
PDataModuleItem = ^TDataModuleItem;
TDataModuleItem = packed record
Key : Pointer;
Value : Pointer;
datatype: word;
Size : integer;
end;
Dann baust du dir nen interface, das du an die
DLL übergibst und den Zugriff auf die Listenelemente bereitstellt:
Delphi-Quellcode:
IDataModule = interface(IEnumerator)
['{57AF81B3-B7A8-4B33-8174-C2DBA70DAC97}']
function GetLinked: boolean; stdcall;
procedure GetLink(out Link); stdcall;
procedure SetLink(const ALink: IInterface); stdcall;
procedure RemoveLink; stdcall;
function GetValueCount: integer; stdcall;
function GetValue(index: integer): Pointer; stdcall; // liefert PDataModuleItem zurück
procedure SetValue(index: integer; Value: Pointer); stdcall;
procedure DeleteValue(index: integer); overload; stdcall;
procedure DeleteValue(Key: PChar); overload; stdcall;
function HasValue(Key: PChar): boolean; stdcall;
procedure SetCharValue(AKey: PChar; AValue: PChar); stdcall;
function GetCharValue(AKey: PChar): PChar; stdcall;
procedure SetFloatValue(AKey: PChar; AValue: real); stdcall;
function GetFloatValue(AKey: PChar): real; stdcall;
procedure SetIntValue(AKey: PChar; AValue: Int64); stdcall;
function GetIntValue(AKey: PChar): Int64; stdcall;
procedure SetBoolValue(AKey: PChar; AValue: boolean); stdcall;
function GetBoolValue(AKey: PChar): boolean; stdcall;
property ValueCount: integer read GetValueCount;
property Linked: boolean read GetLinked;
end;
Das interface kann gleich noch nen interface besitzen, dass als Link fungiert und dem Besitzer mitteilt ob sich was geändert hat
Jetzt musst du dir nur noch ne Klasse definieren, die dieses Interface implementiert und schon kannst du das in die
DLL rüberschicken bei Bedarf. Als Auszug könnte das so aussehen
Delphi-Quellcode:
function TCustomDataModule.GetCharValue(AKey: PChar): PChar;
var index: integer;
begin
result := nil;
index := IndexOf(AKey);
with FList.LockList do
try
if (index > -1) and
(PDataModuleItem(Items[index])^.datatype = STR_DATA) then
result := PChar(PDataModuleItem(Items[index])^.Value);
finally
FList.UnlockList;
end;
end;
procedure TCustomDataModule.SetCharValue(AKey: PChar; AValue: PChar);
var Buffer: PDataModuleItem;
begin
Buffer := nil;
// if IndexOf(AKey) > -1 then
try
Buffer := NewDataModuleItem(STR_DATA);
Buffer^.Key := CopyPChar(AKey);
Buffer^.Value:= CopyPChar(AValue);
SetValue(IndexOf(AKey),Buffer);
finally
DisposeDataModuleItem(Buffer);
end;
end;
procedure TCustomDataModule.SetValue(index: integer; Value: Pointer);
var Buffer: PDataModuleItem;
begin
Buffer := nil;
if (index > -1) and (index < ValueCount) then
with FList.LockList do
try
Buffer := Items[index];
finally
FList.UnlockList;
end;
if Assigned(Buffer) then
begin
LinkNotification(Buffer^.Key, Buffer^.datatype, lnsChanging);
DisposeDataModuleItem(Buffer);
end;
Buffer := CopyDataModuleItem(PDataModuleItem(Value));
if Assigned(Buffer) then
with FList.LockList do
try
if (index > -1) and (index < Count) then
Items[index] := Buffer
else
Add(Buffer);
LinkNotification(Buffer^.Key, Buffer^.datatype, lnsChanged);
finally
FList.UnlockList;
end;
end;
FList is ne ThreadList, damit bist du auch noch Threadsafe, LinkNotification ist ne Methode des Datenmoduls, die bei Bedarf dem Link mitteilt dass sich was geändert hat
Ach und ebenso gesundes neues
Edit\\ CopyDataModuleItem kopiert das record, wobei du dann je nach pItem^.datatype die Werte sinnvoll kopieren solltest