Einzelnen Beitrag anzeigen

snook

Registriert seit: 25. Jun 2010
94 Beiträge
 
Delphi 2005 Professional
 
#2

AW: Übergabe von Listen an DLL ohne Kopie zu erstellen.

  Alt 2. Jan 2012, 15:41
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

Geändert von snook ( 2. Jan 2012 um 15:46 Uhr)
  Mit Zitat antworten Zitat