![]() |
InterfaceTable eines Interfaces?
Nun hab ich mal so eine ganz kuriose Sache, jedes TObject hat ja die bekannte Funktion "GetInterfaceTable"...
Komme ich über ein Interface auch an diese Tabelle? Sprich ich hab ein Variable Intf: IUnknown, welche auch belegt ist, dass Object dahinter ist mir völlig unbekannt... Nun würde ich gern alle GUIDs der implementierten Interfaces haben... Bis jetzt mach ich es pie mal daumen so (Achtung, das ist nur ein grobes Funktionsbeispiel... :duck: ):
Delphi-Quellcode:
Nunja, aber da kann man ja schnell mal ein Interface vergessen, daher wär so eine Tabelle schon eine sehr feine Sache...
Function GetGUIDs( Const Intf: IUnknown ): {irgendwas...}
Begin If Supports( Intf, IInt1 ) Then {lalala}.Add( GUIDToString( IInt1 ) ); If Supports( Intf, IInt2 ) Then {lalala}.Add( GUIDToString( IInt2 ) ); If Supports( Intf, IInt3 ) Then {lalala}.Add( GUIDToString( IInt3 ) ); If Supports( Intf, IInt4 ) Then {lalala}.Add( GUIDToString( IInt4 ) ); If Supports( Intf, IInt5 ) Then {lalala}.Add( GUIDToString( IInt5 ) ); { Mach mir ein wildes Result... } End; Vorallem, da ja eventuell mal ein neueres Modul mit einem alten Programm läuft, welches ja ev. mal das Interface nicht kennt (macht die Liste dannn ja unvollständig)... Hat jemand eine Idee? :gruebel: Bye Christian |
Re: InterfaceTable eines Interfaces?
Ok ich hab mal einen kleinen Umweg versucht:
Delphi-Quellcode:
Nunja aber da is das Result immer Nil... liegt wohl daran, dass das Interface über eine DLL eingeladen wird, da fehlen wohl die RTTI...
Type
IIntfTbl = Interface ['{C93CB029-F127-493C-9A65-8C5E446BE830}'] Function GetObjInterfaceTable: PInterfaceTable; StdCall; End; {...} TBasisModulDingens = Class( TInterfacedObject, {viele weitere Interfaces...}, IIntfTbl ) {...} Protected { Protected-Deklaration } Function GetObjInterfaceTable: PInterfaceTable; StdCall; {...} End; {...} Function TBasisModulDingens.GetObjInterfaceTable: PInterfaceTable; Begin Result := GetInterfaceTable; End; {...} Richtig? Nunja kann man das dennoch irgendwie realisieren? Bye Christian |
Re: InterfaceTable eines Interfaces?
*push*
|
Re: InterfaceTable eines Interfaces?
Suche immer noch nach einer einfacehn Lösung bzw. einen Lösungsansatz...
:duck: Bye Christian |
Re: InterfaceTable eines Interfaces?
*push* In Hoffnug auf eine Lösung :zwinker:
|
Re: InterfaceTable eines Interfaces?
probiere mal
Delphi-Quellcode:
Du baust dir quasi eine einfache Iteriermethode die dir alle unterstützten GUIDs aller Klassen der Vererbungshierarchie zurückgibt.
type
IIntfTbl = Interface ['{C93CB029-F127-493C-9A65-8C5E446BE830}'] function SupportsInterface(Index: Integer; out GUID: TGUID): Bool; stdcall; end; function TXyz.SupportsInterface(Index: Integer; out GUID: TGUID): Bool; stdcall; var Table: PInterfaceTable; Class: TClass; begin Result := False; Class := ClassType; while (Index >= 0) and (Class <> nil) do begin Table := Class.GetInterfaceTable; if Table <> nil then if Index < Table.EntryCount then begin Move(Table.Entries[Index], GUID, SizeOf(TGUID)); Result := True; Exit; end else Dec(Index, Table.EntryCount); Class := Class.ParentClass; end; end; procedure Test; var I: Integer; IntfTbl: IIntfTbl; GUID: TGUID; begin I := 0; if IUnknown.QueryInterface(IIntfTbl, IntfTbl) = S_OK then while IntfTbl.SupportsInterface(I, GUID) do begin ..... tue was mit GUID Inc(I); end; end; Ein Zugriff direkt auf die RTTI's über Modulgrenzen hinweg ist eine sehr sehr schlechte Idee, dh. den Zeiger auf die PInterfaceTable zurückzugeben ist kontraproduktiv. Gruß Hagen |
Re: InterfaceTable eines Interfaces?
Das Prinzip funktioniert :thumb:
Hab schon gar nicht mehr an eine Lösung geglaubt... Hmm, nur hat ich sowas in der Art auch versucht, nur war der Pointer zur Table immer NIL... Ich hab mir das noch ein wenig zusammengestutzt, rausgekommen ist das: (Falls nochmal jemand sowas brauch)
Delphi-Quellcode:
Bye Christian
Type
IInterfaceTable = Interface ['{19B847B4-37F6-40A7-A999-6AF680D6CFE2}'] Function GetCount: Integer; StdCall; Function GetItem( Index: Integer ): TGUID; StdCall; { *** } Property Count: Integer Read GetCount; Property Items[ Index: Integer ]: TGUID Read GetItem; Default; End; { ... } Type TaObj = Class( {...}, IInterfaceTable ) Protected { Protected-Deklaration } Function ITGetCount: Integer; StdCall; Function ITGetItem( Index: Integer ): TGUID; StdCall; Function ITGetRefItem( Index: Integer ): TGUID; StdCall; Function IInterfaceTable.GetCount = ITGetCount; Function IInterfaceTable.GetItem = ITGetItem; { ... } Public { Public-Deklaration } Property IntfCount: Integer Read ITGetCount; Property IntfItems[ Index: Integer ]: TGUID Read ITGetItem; { ... } End; { ... } Const cNullGUID: TGUID = ( D1: $00000000; D2: $0000; D3: $0000; D4: ( $00, $00, $00, $00, $00, $00, $00, $00 ); ); { ... } Function TaObj.ITGetRefItem(Index: Integer): TGUID; Var Table: PInterfaceTable; aClass: TClass; Res: Boolean; Begin Res := False; aClass := ClassType; While ( Index >= 0 ) And ( aClass <> Nil ) Do Begin Table := aClass.GetInterfaceTable; If Table <> Nil Then Begin If Index < Table.EntryCount Then Begin // Move( Table.Entries[ Index ], GUID, SizeOf( TGUID ) ); Result := Table.Entries[ Index ].IID; Res := True; Break; End Else Begin Dec( Index, Table.EntryCount ); End; End Else Begin // Keine Tabelle vorhanden... End; aClass := aClass.ClassParent; End; If Not Res Then Result := cNullGUID; End; Function TaObj.ITGetCount: Integer; Var Table: PInterfaceTable; aClass: TClass; Begin aClass := ClassType; If ( aClass <> Nil ) Then Begin Result := 0; While ( aClass <> Nil ) Do Begin Table := aClass.GetInterfaceTable; If ( Table <> Nil ) Then Inc( Result, Table.EntryCount ); aClass := aClass.ClassParent; End; End Else Begin Result := -1; // Kein "InterfaceTable" vorhanden... End; End; Function TaObj.ITGetItem( Index: Integer ): TGUID; Var IntfCnt: Integer; nIdx: Integer; Begin IntfCnt := ITGetCount; If ( Index >= 0 ) And ( Index < IntfCnt ) Then Begin nIdx := IntfCnt - Index - 1; Result := ITGetRefItem( nIdx ); End Else Begin Result := cNullGUID; End; End; |
Re: InterfaceTable eines Interfaces?
Aber so neben bei, kommt man auch an den Interface-Namen ran?
Bye Christian |
Re: InterfaceTable eines Interfaces?
Ich beobachte wohlwollend, was du hier machst :mrgreen: (persönliches Interesse) Hab nur grad keine Zeit da mitzuprobieren.
Was ist denn mit PInterfaceentry := getInterfaceEntry ? |
Re: InterfaceTable eines Interfaces?
Zitat:
Zitat:
Eigendlich sind in der Tabelle "TInterfaceEntry"s, die brauch ich ja nicht =p Die Interface Liste ist ja eigendlich abgearbeitet, ich kann ja alle GUIDs auflisten die nun irgendwie, irgendwo reinimplementiert werden... Nur richtig schön wäre es nun noch den passenden Namen zu haben (der In Delphi verwendet wird z.b. IInterface), falls man da überhaupt rann kommt... :duck: Bye Christian |
Re: InterfaceTable eines Interfaces?
Zitat:
Gruß Hagen |
Re: InterfaceTable eines Interfaces?
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Delphi-Quellcode:
über die PTypeInfo^ und TypInfo.GetTypeData(PTypeInfo)^ kommst du an den Namen der Interfaces und auch an alle aufrufbaren Methoden samt Parametern.
function FindTypeInfo(const AGUID: TGUID; AModule: LongWord = allModules): PTypeInfo; overload;
Gruß hagen PS: hoffe das du meine Unit nicht in deine Sourcecode Formatierung (wenn man es so bezeichnen möchte) umbaust ;););) |
Re: InterfaceTable eines Interfaces?
Nochwas ist mir aufgefallen
Delphi-Quellcode:
du gibts in diesen Methoden einen "komplexen" Datentyp zurück. Das ist bei Interfaces eher unerwünscht. Normalerweise sollte man Interface so konstruieren das sie HResult zurückgeben oder Bool um anzuzeigen das die Funktion fehlgeschlagen oder nicht fehlgeschlagen ist. Komplexere Datentypen gibt man bei Interfaces als Parameter -> out -> zurück. Dies ist nun kein "muß" und Ausnahmen bestätigen die Regel aber es ist eine sinnvolle Designrichtlinie. Ja ich weis das dann indizierte Properties nicht möglich sind, was ich bei Interfaces ohne Sichtbarkeitskapselungen per private/protected etc.pp. eh als sinnlose Erfindung der Bolandianer erachte. Sogesehen empfinde ich deine Konstruktion per indizierter Property -> ITGetItem() etc.pp. als dem Interface-Konzept widersprechend. Interfaces sollen eigentlich ausschließlich nur das deklarieren was public sichtbar sein soll. Deine .GetItem() Methode ist aber eine implementierende Schnittstelle und müsste normalerweise unsichtbar im Interface sein. Da dies Borland aber nicht bei Interfaces unterstützt halte ich es für besser komplett auf dieses Property-Sprachkonstrukt bei Interfaces zu verzichten. Das macht die Schnittstelle letzendlich kompakter, übersichtlicher und somit besser wartbar. Anders ausgedrückt: weniger ist manchesmal mehr, man muß nicht jedes mögliche Sprachkonstrukt benutzen ;)
Function ITGetItem( Index: Integer ): TGUID; StdCall;
Function ITGetRefItem( Index: Integer ): TGUID; StdCall; Gruß Hagen |
Re: InterfaceTable eines Interfaces?
Erstmal danke für deine ausführlichen Antworten! Muss erstmal alles überblicken...
Zitat:
Zitat:
Zitat:
:duck: Zitat:
Und bis auf die 2 Wortdreher im Code ist er auch absolut genau der Lösungsansatz den ich gesucht hatte, von daher nochmal danke :spin: Im Grunde war mein Teil nur ein kleiner Ergebnissbericht, falls nochmal jemand damit arbeiten mag und keine Lösung findet... Ich hab ewig gesucht und nix gefunden =( Nungut, ich werd mir das mit dem Interface Namen nachher noch näher anschauen. Bye Christian :hi: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:36 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