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.