Einzelnen Beitrag anzeigen

snook

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

interface und variable des implementierenden objekts

  Alt 11. Dez 2011, 17:13
Delphi-Version: 5
Hallo,

wie der titel suggeriert geht es um ien verhalten welches mir jetzt schon öfter auf die füße gefallen ist. Ich schildere das problem mal an meinem aktuelen beispiel um evtl fehler meinerseits aufzuklären.

Ich benutze recht exzessiv interfaces, da mein hauptprojekt die arbeit mit DLL's erfordert. Nehmen wir ein interface.
Delphi-Quellcode:
  IDataChangeLink = interface
  ['{05247DCC-84D0-4A7D-AA35-27FABEE3BBE4}']
    procedure InstallLink(const AModule: IDataModule); stdcall;
    procedure RemoveLink(const AModule: IDataModule); stdcall;
    procedure DataChanging(const AModule: IDataModule; AKey: PChar;
      ADataType: word); stdcall;
    procedure DataChanged(const AModule: IDataModule; AKey: PChar;
      ADataType: word); stdcall;
    procedure DataAdded(const AModule: IDataModule; AKey: PChar;
      ADataType: word); stdcall;
    procedure DataRemoved(const AModule: IDataModule; AKey: PChar;
      ADataType: word); stdcall;
    function GetFLags: LongWord; stdcall;
    procedure SetFlags(const Value: LongWord); stdcall;
  end;
Es geht nun insbesondere um die Methoden GetFlags und SetFlags . Ein objet, welches das ganze implementiert sieht nun so aus:
Delphi-Quellcode:
  TCustomDataModuleLink = class(TInterfacedObject, IDataChangeLink)
  private
    FFlags : LongWord;
  protected
    function GetFLags: LongWord; stdcall;
    procedure SetFlags(const Value: LongWord); stdcall;
    ...
  public
    ...
    property Flags: LongWord read GetFlags write SetFlags;
  end;

function TCustomDataModuleLink.GetFLags: LongWord;
begin
  result := FFlags;
end;

procedure TCustomDataModuleLink.SetFlags(const Value: LongWord);
begin
  FFlags := Value;
end;
Ein Objekt dass dieses Interface verwendet sei mal so definiert;
Delphi-Quellcode:
  TCustomDataModule = class(TCountedInterfacedObject, IDataModule)
  private
    FLink : IDataChangeLink;
    function GetLinked: boolean; stdcall;
  public
    constructor Create(AName: PChar; ADataLink: IDataChangeLink = nil); reintroduce; virtual;
    destructor Destroy; override;

    //IDataModuleInterface
    procedure GetLink(out Link: IInterface); stdcall;
    procedure SetLink(const ALink: IInterface); stdcall;
Jetzt erzeuge ich dieses Objekt in DLL A und übergebe eine Referenz (temp) auf IDataModule an ein Objekt in DLL B. in DLL B rufe ich dann
Delphi-Quellcode:
procedure TDataModuleInspector.ChangeFlags(const temp: IDataMOdule; AFlag: LongWord);
var lLink: IDataCHangeLink;
begin
  temp.GetLink(IInterface(LLink));
  if Assigned(lLink) then
    try
      lLink.SetFlags(lLink.GetFlags xor AFlag);
    finally
      lLink := nil;
    end;
end;
Überprüfe ich nach diesem Aufruf den Wert Flags von lLink, dann ist der auch richtig geändert worden. Jetzt wird es für mich unverständlich. In einer weiteren Methode greife ich auf den Wert Flags zu;
Delphi-Quellcode:
function TDataModuleInspector.AllowWrite(const ADataModule: IDataModule): boolean;
var lLink: IDataChangeLink;
begin
  result := false;
  if not Assigned(ADataModule) then
    exit;
  lLink := nil;
  if ADataModule.Linked then
    ADataModule.GetLink(IInterface(lLink));
  if Assigned(lLink) then
    try
      result := (lLink.GetFlags and DML_ALLOW_WRITE) = DML_ALLOW_WRITE;
    finally
      lInspLink := nil;
      lLink := nil;
    end;
  end;
Wobei temp an diese Methode übergeben wurde. hier hat sich jedoch nichts getan!!!! egal wie oft ich ChangeFlags oben aufrufe, der Wert den ich erhalten wenn ich danach GetFlags aufrufe ist immer noch der gleiche!!!! Was mache ich falsch?

Um das ganze mal zusammenzufassen. Ich habe es jetzt schon oft bemerkt, dass eine referenz auf ein interface, welche in einer anderen DLL verwendet wird schwierigkeiten hat, Variablen im implementierenden objekt zu setzen. Es scheint, als ob während der methode, in der eine variable gesetzt wird, so etwas wie temporärrer speicher angefordert wird, in dem dann eine kopie des objektes abgelegt wird. nach dem aufruf wird das ganze dann wieder freigegeben. So würde ich dannauch während des Aufrufes "sehen" wie die Variable gesetzt wird, danach die Änderung aber wieder verworfen wird. Das lustige ist ja, dass wenn ich in dem Modul, in dem das objekt erstellt wurde die Interface-Methoden verwende um lokale Variablen zu setzen, diese dann auch bestehen bleiben. Ich wundere mich allerdings auch darüber, dass ich dieses Verhalten nicht durchweg erhalte. Manchmal funktionieren dies Aufrufe und ändern tatsächlich die lokalen Variablen.

Geändert von snook (11. Dez 2011 um 17:23 Uhr)
  Mit Zitat antworten Zitat