![]() |
TypeInfo über IID oder Klasse (und RTTI)
Hallo zusammen,
nach meiner Auffassung besitzt jedes Interface mit IID, das von einer Klasse implementiert wird auch TypInfoformationen, die über den Aufruf von
Delphi-Quellcode:
abgefragt werden können. Sieht man sich das Kompilat genauer an, ist eine "magische" Adresse zu erkennen, an der eine Referenz auf die Daten abgelegt ist. Diese Zahl wird auch bei Aufrufen von TypeInfo bei anderen Typen vom Compiler generiert und kann meines Wissens nicht anders als eben über diese Funktion/Operator erlangt werden.
TypeInfo(IAnInterfaceName)
Objekte und Klassen bieten mit TObject.ClassInfo darüber hinaus auch zur Laufzeit die Möglichkeit, auf dieser Daten zuzugreifen, so dass Konstruktue wie
Delphi-Quellcode:
u.a. erlauben, den Unitbezeichner der Klasse eines Objekts zu ermitteln (sofern die Klasse mit Typinformationen kompiliert wurde, siehe OH).
function GetUnit(const AnObject: TObject): string;
begin Result := GetTypeData(AnObject.ClassInfo).UnitName; end; Mein Problem ist etwas anders gestaltet. Ich suche nach einer Möglichkeit, die erste Referenz auf ein TTypeInfo-Record des Interfaces mit einem IID einer Klasse oder seinem Vorfahren zu erlangen.
Delphi-Quellcode:
Der Rückgabewert von GetTypeInfoOfFirstInterface sollte im skizzierten Fall dasselbe Resultat bringen wie
type
IMyInterface = interface ['AnIID'] procedure AMethod; end; TMyClass = TInterfacedObject(IMyInterface) procedure AMethod; end; function GetTypeInfoOfFirstInterface(const AClass: TClass): PTypeInfo;
Delphi-Quellcode:
Über TObject.GetInterfaceTable bekomme ich für jedes durch eine Klasse implementierte Interface mit IID eine Referenz auf das Record TInterfaceEntry mit
Assert( TypeInfo(IMyInterface)=GetTypeInfoOfFirstInterface(TMyClass) );
Delphi-Quellcode:
ich kann aber leider nicht entdecken, ob ich auf diesem Weg an die Typinformationen herankomme.
type
TInterfaceEntry = packed record IID: TGUID; VTable: Pointer; IOffset: Integer; ImplGetter: Integer; end; Selbstverstädnlich würde sich auch eine Technik anbieten, bei der die Typinformationen (sofern vorhanden) über einen IID ermittelt werden. Weiß jemand von Euch eine Lösung? |
Re: TypeInfo über IID oder Klasse (und RTTI)
nein über diesen Weg geht das leider nicht da der Compiler in den RTTI einer Klasse über die PInterfaceTable nur die durch die Klasse implementierten Interface die Infos ablegt. Der RTTI Record über ein IInterface ist dabei was komplett anderes und das einzigst Gemeinsamme in beiden RTTI-Records ist die GUID.
Ich habe hier im Forum mal einen "inoffiziellen" Weg gepostet, samt Source, wie man aber über die TypInfos eines kompletten Modules iterieren kann. Mit dieser Methode wäre es nun möglich eine Funktion zu coden die zu einer GUID die TypeInfo dieses IInterfaces ermittelt. Allerdings dürfte das garnicht notwendig sein :)
Delphi-Quellcode:
Wie man aber unschwer erkennen kann ist dieser Weg im Grunde "doppelgemoppelt" denn so ginge es viel einfacher
function HasInterface(AClass: TClass; ATypeInfo: PTypeInfo): Boolean;
begin Result := (ATypeInfo <> nil) and (ATypeInfo.Kind = tkInterface) and (AClass <> nil) and (AClass.GetInterfaceEntry(GetTypData(ATypeInfo).GUID) <> nil); end; procedure Test; begin if HasInterface(TypeInfo(IMyInterface), TMyClass) then ... end;
Delphi-Quellcode:
Da die "function TypeInfo()" ein Compiler Magic ist, also schon zur Kompilierungszeit wird TypeInfo() aufgelösst und im fertigen Code steht nur noch ein "Zeiger ins Codesegment", gibt es eh keinen Weg die ganze Sache dynamisch zur Laufzeit zu machen.
procedure Test;
begin if TMyClass.GetInterfaceEntry(IMyInterface) <> nil then with TypeInfo(IMyInterface) do end; Gruß Hagen |
Re: TypeInfo über IID oder Klasse (und RTTI)
könnt ihr nich auch einfach
if Supports(TDeineClass, IDeinInterface) then ... nehmen? |
Re: TypeInfo über IID oder Klasse (und RTTI)
Hallo Hagen :),
![]() ![]() Hast Du eine Ahnung, ob das mit Delphi2005 gegen Win32 klappt? |
Re: TypeInfo über IID oder Klasse (und RTTI)
Hallo barf00s und nochmal Hagen,
Routinen der Art Supports und HasInterface beantworten wie skizziert die folgende Frage Zitat:
Zitat:
Aus meiner aktuellen Perspektive bleibt keine andere Möglichkeit, als mit Hagens Routine (s.o.) alle Typinformationen nach einem Interfacetyp mit einem übereinstimmenden IID zu durchsuchen (bzw. in einer suchbaren Struktur zu registrieren). Ich würde aber gerne eine... sagen wir... Delphi-artige Lösung verwenden ;), die wie AnObject.ClassName auch die nächsten 9 Versionen von Delphi Bestand haben wird und gleichfalls auf Essenziellem beruht, so das ggf. sogar eine spätere Portierung nach .net in Betracht kommt. |
Re: TypeInfo über IID oder Klasse (und RTTI)
darf man fragen was du überhaupt mit diesem dingen bezwecken willst?
|
Re: TypeInfo über IID oder Klasse (und RTTI)
@Barfoos:
schau dir mal in SysUtils.pas die Implementation von Supports() genauer an. Es ginge also schon aber du benötigst ein alloziertes Object statt einer Klasse und wenn das Object dieses Interface unterstützt wird intern schon eine neue Refernez auf diese Interface gezogen. Das bedeutet der Code von Supports() ist keine passive Abfrage ob eine Klasse/Object ein Interface unterstützt sondern im gegenteil eine aktive Abfrage indem testweise das Interface angefordert wird. @Choose: ich glaube schon das Delphi auch weiterhin meinen Trick unterstützen wird. Immerhin handelt es sich hier um langjähriges und altbewährtes Vorgehen innerhalb des Compilers. Sollte sich daran was ändern so würde das für Borland einen immensen Aufwand an Änderungen im Compiler bedeuten. Man kann ja per Compiler Defines die entsprechende Compilerversion in meinem Source abfragen und falls der Source dann auf einer neuen Version compiliert wird gibt man im Source eine Fehlermeldung aus. Man muß also dann erstmal einen kleinen Testcode mit der neuen Version laufen lassen, feststellen ob's noch funktioniert und dann gegebenfalls die neue Version in die Compiler Defines einbauen. So stellt man auf alle Fälle sicher das man diesen sensiblen Code nicht ohne Warnungen verwendet. Ich vermute mal das dein obiger Beispiel Source nur eine verkürzte Variante darstellt, d.h. das du im fertigen Source eben dynamisch zur Laufzeit diese TypInfo-Überprüfungen durchführen möchtest (anders macht deine Frage eigentlich keinen Sinn). Nun, und in diesem Szenario sehe ich nur den Weg über meine Funktion zur Iteration der TypInfos. Gruß Hagen |
Re: TypeInfo über IID oder Klasse (und RTTI)
Ich würde erstmal mit meinem Code arbeiten. Du benutzt eine TList in der du alle @TypeInfo vom Type tkInterface sammelst. Diese TList ist mit einer eigenen Sort Callback sortiert nach der GUID der GetTypeData(PTypeInfo).GUID. So kannst du nach der Erzeugung dieser TList sehr schnell nach der GUID darin suchen, ebenfalls mit einer speziellen Suchfunktion. Das alles ausgelagert in eine eigene Unit die per Compiler Defines auf die getesteten Delphi Versionen geschützt wurde.
Gruß Hagen |
Re: TypeInfo über IID oder Klasse (und RTTI)
Hallo barf00s,
ich ergänze gerade mein Framework zur ![]() Trotzdem beschreiben viele der Container Abhängigkeiten zu speziellen Interfaces (Services), die ihrerseits nun durch das Plug-In-Framework nachgeladen werden. Weil ich das Plug-In-Framework des Drittherstellers nicht verändern und schon gar nicht in den Registraturmachnismus dieser Plug-ins eingreifen möchte, bleibt zur Ermittlung des (ersten, es handelt sich um einen Service) unterstützen Interfacetyps aus meiner Sicht nur die Möglichkeit, sie aus der Klassenreferenz zu extrahieren. Oder übersehe ich etwas? :gruebel: |
Re: TypeInfo über IID oder Klasse (und RTTI)
Hallo Hagen,
Zitat:
Delphi-Quellcode:
function Supports(const AClass: TClass; const IID: TGUID): Boolean;
begin Result := AClass.GetInterfaceEntry(IID) <> nil; end; Zitat:
Hat jemand die Anwendbarkeit der ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:07 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz