AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Gleiche Interface-Referenzen?

Ein Thema von himitsu · begonnen am 6. Mär 2015 · letzter Beitrag vom 6. Mär 2015
Antwort Antwort
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
42.413 Beiträge
 
Delphi 2 Desktop
 
#1

Gleiche Interface-Referenzen?

  Alt 6. Mär 2015, 00:35
n'abend,

ist es nur Zufall, oder haben abgeleitete Interfaces in den Objekten wirklich "immer" die selben Referenzen?
Auch in anderen Plattformen und nicht nur im Windows.
Delphi-Quellcode:
type
  IFoo = interface
    ['{05C90FF9-4788-49FB-9C60-CA901F8BBEBA}']
    procedure Foo;
  end;
  IBar = interface(IFoo)
    ['{01B62A8B-40E4-417C-AC63-F787C26DA89F}']
    procedure Bar;
  end;
  IBlubb = interface
    ['{A35EE740-965E-4F97-9AC2-A99F165B0322}']
    procedure Foo;
  end;
  TFooBar = class(TInterfacedObject, IBar, IFoo, IBlubb)
    procedure Bar;
    procedure Foo;
  end;

procedure TForm3.FormCreate(Sender: TObject);
var
  F: IFoo;
  B: IBar;
  X: IBlubb;
begin
  B := TFooBar.Create as IBar;
  F := B;
  Memo1.Lines.Add(Format('$%p $%p', [Pointer(B), Pointer(F)]));
  F := B as IFoo;
  Memo1.Lines.Add(Format('$%p $%p', [Pointer(B), Pointer(F)]));

  F := TFooBar.Create as IFoo;
  B := F as IBar;
  Memo1.Lines.Add(Format('$%p $%p', [Pointer(F), Pointer(B)]));

  X := B as IBlubb;
  Memo1.Lines.Add(Format('$%p $%p', [Pointer(F), Pointer(X)]));
end;

procedure TFooBar.Bar;
begin
end;

procedure TFooBar.Foo;
begin
end;
Im Grunde geht es darum, ob bei procedure Test(Ref: IFoo); die Interfaces immer die selbe Referenz besitzen
und man dieses "Objekt" somit immer zuverlässig in Listen finden kann oder ob ich doch besser immer die interen Objekt-Referenzen vergleichen muß,
bzw. ob ich zu Beginn immer das Interface geziehlt auf ein Bestimmtes casten (Supports/AS) sollte.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 6. Mär 2015 um 00:38 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Gleiche Interface-Referenzen?

  Alt 6. Mär 2015, 01:21
Es ist da doch etwas komplizierter:
Delphi-Quellcode:
program dp_184186;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

type
  IFoo = interface
    ['{E4CA5AB6-B9DF-403C-B30B-72636041B010}']
  end;

  IBar = interface( IFoo )
    ['{6DFEAA0D-E3CA-4DCE-8450-7E54DC6DD7AC}']
  end;

  TFoo = class( TInterfacedObject, IFoo )
  end;

  TBar = class( TInterfacedObject, IBar )
  end;

  TFooBar = class( TFoo, IBar )
  end;

  TFooFooBar = class( TFoo, IFoo, IBar )
  end;

procedure PrintIntfRef( const RefName: string; const Ref: IInterface );
begin
  Writeln( Format( '%s($%p)', [RefName, Pointer( Ref )] ) );
end;

procedure PrintFoo( const AFoo: IFoo );
begin
  PrintIntfRef( 'IFoo', AFoo );
end;

procedure PrintBar( const ABar: IBar );
begin
  PrintIntfRef( 'IBar', ABar );
end;

procedure Test;
var
  LBar: IBar;
begin
  Writeln( 'TBar' );
  LBar := TBar.Create;
  PrintFoo( LBar );
  // PrintFoo( LBar as IFoo ); // EIntfCastError
  PrintBar( LBar );

  Writeln( 'TFooBar' );
  LBar := TFooBar.Create;
  PrintFoo( LBar );
  PrintFoo( LBar as IFoo );
  PrintBar( LBar );

  Writeln( 'TFooBar' );
  LBar := TFooFooBar.Create;
  PrintFoo( LBar );
  PrintFoo( LBar as IFoo );
  PrintBar( LBar );
end;

begin
  try
    Test;
  except
    on E: Exception do
      Writeln( E.ClassName, ': ', E.Message );
  end;
  ReadLn;

end.
Und die Lösung lautet hier:
Delphi-Quellcode:
procedure PrintFooAsFoo( const AFoo: IFoo );
var
  LFoo: IFoo;
begin
  if Supports( AFoo, IFoo, LFoo )
  then
    PrintIntfRef( 'IFoo', LFoo )
  else
    PrintIntfRef( 'IFoo', AFoo );
end;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 6. Mär 2015 um 01:55 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
3.995 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#3

AW: Gleiche Interface-Referenzen?

  Alt 6. Mär 2015, 08:29
ist es nur Zufall, oder haben abgeleitete Interfaces in den Objekten wirklich "immer" die selben Referenzen?
Für die Interface table nimmt der Compiler hier tatsächlich denselben Slot, soweit in derselben Klasse implementiert, um die Instancesize möglichst gering zu halten.
Ob das auch für die mobilen Plattformen gilt, kann ich dir nicht sagen, aber ist mit folgendem Code einfach herauszufinden:

Delphi-Quellcode:
var
  table: PInterfaceTable;
  entry: PInterfaceEntry;
  i: Integer;
begin
  table := TFooBar.GetInterfaceTable;
  for i := 0 to table.EntryCount - 1 do
    Writeln(GUIDToString(table.Entries[i].IID), ' ', table.Entries[i].IOffset);
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
42.413 Beiträge
 
Delphi 2 Desktop
 
#4

AW: Gleiche Interface-Referenzen?

  Alt 6. Mär 2015, 08:59
Mist, dann werde ich wohl doch eine Typ-Prüfmethode Vorsoglich-Umwandlungsmethode (Supports) einbauen müssen.

Eine Tyüprüfung ala IS (if not (Value is IFoo) then Value := Value as IFoo; ) geht ja nicht.
Bei Objekten zeigen unterschiedlich gecastete "Typen" ja immer auf die selbe Adresse und für Objekte kenn ich nichts, um den Interface-Typ hinter einem Interface festzustellen, sowas wie if Value.Type = IFoo .

Dachte ich kann mir die zusäztlichen Operationen sparen, welche ja wild mit der Referenzzählung und zusätzlichen Variablen rumfuchteln.



Also hier nutzen die schon nicht mehr den selben Slot,
außer man deklariert TFooBar so class(TFoo, IBar, IFoo, IBlubb) .

Da die Klasse nur intern ist, kann ich erzwingen, daß es genau so definiert wäre, aber ob der Code dann sicher wäre.
Delphi-Quellcode:
type
  IFoo = interface
    ['{05C90FF9-4788-49FB-9C60-CA901F8BBEBA}']
    procedure Foo;
  end;
  IBar = interface(IFoo)
    ['{01B62A8B-40E4-417C-AC63-F787C26DA89F}']
    procedure Bar;
  end;
  IBlubb = interface
    ['{A35EE740-965E-4F97-9AC2-A99F165B0322}']
    procedure Foo;
  end;
  TFoo = class(TInterfacedObject, IFoo)
    procedure Foo;
  end;
  TFooBar = class(TFoo, IBar, IBlubb)
    procedure Bar;
  end;

procedure TForm3.FormCreate(Sender: TObject);
var
  F: IFoo;
  B: IBar;
  X: IBlubb;
begin
  B := TFooBar.Create as IBar;
  F := B;
  Memo1.Lines.Add(Format('$%p $%p', [Pointer(B), Pointer(F)]));
  F := B as IFoo;
  Memo1.Lines.Add(Format('$%p $%p', [Pointer(B), Pointer(F)]));

  F := TFooBar.Create as IFoo;
  B := F as IBar;
  Memo1.Lines.Add(Format('$%p $%p', [Pointer(F), Pointer(B)]));

  X := B as IBlubb;
  Memo1.Lines.Add(Format('$%p $%p', [Pointer(F), Pointer(X)]));
end;

procedure TFooBar.Bar;
begin
end;

procedure TFoo.Foo;
begin
end;

Aber vielleicht lass' ich es erstmal so und bau mir eine Methode, welche am Anfang die InterfaceTable ausslist und prüft.
Müsste ja jedes Interface, was von außerhalb meiner Klasse kommt immer schön prüfen und umwandeln, bevor es in den Listen landet und/oder verglichen wird.

Statt einem
Zitat:
if Value as TFoo = Self then
wollte ich schon ein if Value.IsSelf(Self) then einbauen, aber in mobilen macht das keinen Unterschied, da es in beiden Varianten zusätzliche Variablen mit zusätzlichen Referenzen gibt (intern ja das Self).



Ach ... ich denk nochmal 'nen Tag und dann am Abend gucken, was ich (erstmal) mach.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 6. Mär 2015 um 09:06 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
42.413 Beiträge
 
Delphi 2 Desktop
 
#5

AW: Gleiche Interface-Referenzen?

  Alt 6. Mär 2015, 10:21
n'Abend.

Es sind bereits alle Parameter niemals als CONST deklatiert. (Das Problem mit den 0-Referenzen kennen wir nun ja bereits)
Und dann wird es wohl auf eigene Comparer für die Listen hinauslaufen, welche ausschließlich das interne Objekt vergleichen und die Interfaces bleiben so wie sie sind.

Schade nur, daß man keine Interface-Methoden als "private" deklarieren kann.
In einem anderen Interface würde es zwar verstecken, aber dann gibt es wieder zusätzliche Casts und Referenzen.
> muß mir nur überlegen, ob ich diese Methoden öffentlich deklariere, oder ob ich das über Objekt-Referenzen löse.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von NicoDE
NicoDE

Registriert seit: 16. Jul 2012
Ort: Darmstadt
26 Beiträge
 
Delphi 10.3 Rio
 
#6

AW: Gleiche Interface-Referenzen?

  Alt 6. Mär 2015, 13:31
COM schreibt vor, dass ein Objekt für IUnknown immer den selben Zeiger zurückgeben muss (damit die Identität geprüft werden kann).
Und ich gehe mal davon aus, dass Delphi sich mit seinem IInterface auch daran hält (was nicht für Quellen von dritten gelten muss).

ps: so in etwa (ungetestet)
Delphi-Quellcode:
function CompareInterface(AInterface1, AInterface2: IInterface): Integer;
var
  Lhs: IInterface;
  Rhs: IInterface;
begin
  if Assigned(AInterface1) then
    if Failed(AInterface1.QueryInterface(IInterface, Lhs)) then
      Pointer(Lhs) := nil;
  if Assigned(AInterface2) then
    if Failed(AInterface2.QueryInterface(IInterface, Rhs)) then
      Pointer(Rhs) := nil;
  if PAnsiChar(Lhs) > PAnsiChar(Rhs) then
    Result := 1
  else if PAnsiChar(Lhs) < PAnsiChar(Rhs) then
    Result := -1
  else
    Result := 0;
end;
Nico Bendlin

Geändert von NicoDE ( 6. Mär 2015 um 14:17 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
42.413 Beiträge
 
Delphi 2 Desktop
 
#7

AW: Gleiche Interface-Referenzen?

  Alt 6. Mär 2015, 14:26
Ja, bei einem Interface-Typ stimmt das,

aber bezüglich der Interface-Vererbung, sieht das wohl nicht ganz so eindeutig aus.





Es ist garnicht so leicht eine sich selbst referenzierende Baumstrucktur, mit zusätzlichen Verlinkungen, ordentlich hinzubekommen, ohne daß sie sich selbst im Speicher hält und ohne daß abhängige Objekte vorzeitig verschwinden.
Aber ich glaub langsam hab ich's. (aktuell versuchsweise in einem JSON-DOM implementiert)

Nur den Veruch die Speicher-/Referenzverwaltung in generischen Basisklassen zu implementieren und die dann überall zu verwenden, mußte ich leider aufgeben.
(mit Makros wäre es bestimmt gegangen, aber die Generics sind einfach nur )
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 6. Mär 2015 um 14:40 Uhr)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:04 Uhr.
Powered by vBulletin® Copyright ©2000 - 2023, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf