Der schöne Günther 316 Posted June 5, 2019 (edited) You can use the RTTI to evaluate certain properties of interace types. Please see the following snippet: program Project1; uses System.Rtti; var context: TRttiContext; rttiInterface: TRttiInterfaceType; begin context := TRttiContext.Create(); rttiInterface := context.GetType( TypeInfo(IInterface) ) as TRttiInterfaceType; rttiInterface.IntfFlags; // is [ifHasGuid] rttiInterface := context.GetType( TypeInfo(IInvokable) ) as TRttiInterfaceType; rttiInterface.IntfFlags; // is [3]. 3 is not a valid enum value end. You can put a breakpoint on both lines with a comment for evaluating the value of IntfFlags yourself. IInvokable (and every interface that derives from it) has an undocumented value of "3". What does it mean? I have not been able to find anything in the source code. Clearly, System.TypInfo.TIntfFlag is declared as TIntfFlag = (ifHasGuid, ifDispInterface, ifDispatch); Edited June 5, 2019 by Der schöne Günther Share this post Link to post
Remy Lebeau 1396 Posted June 5, 2019 (edited) Are you saying the returned IntfFlags *contains* a bit that *represents* an enum value of 3? Or that the IntfFlags *itself* is a numeric value of 3? In the former case, I have seen something similar before: https://stackoverflow.com/questions/49950534/strange-behaviour-of-typeinfo-by-anonymous-methods In the latter case, the TRttiInterfaceType.IntfFlags property returns a TIntfFlags Set, and a Set is implemented as a bitmask, where each bit represents a specific enum value. A bitmask value of 3 means the 1st 2 bits in the bitmask are set. And since TIntfFlags contains all of the TIntfFlag values, that would mean a bitmask value of 3 has the ifHasGuid and ifDispInterface flags enabled. Which, I guess the latter does not make sense in this situation, because IInvokable is not a dispinterface. So, it must be the former. Edited June 5, 2019 by Remy Lebeau Share this post Link to post
Stefan Glienke 2002 Posted June 5, 2019 (edited) It seems indeed as if the TIntfFlag enum was never extended since Delphi6 (I think that was when interface RTTI was introduced) - I can confirm that at least since XE an interface type with $M+ gets a fourth flag (lets call it ifHasMethodInfo) set. If the type is an anonymous method type (see https://stackoverflow.com/q/49950534/587106) then there is a 7th enum value in the set. The situations where bit 5 and 6 are set are unknown to me. You might want to file an issue in QP about this. @Remy Lebeau Your diagnosis is still wrong - if the debugger shows Quote [(out of bound) 3] then that means it has the 4th bit set. I can confirm my findings with this code: uses SysUtils, Rtti; type TIntfFlagEx = (ifHasGuid, ifDispInterface, ifDispatch, ifMethodInfo, ifUnknown, ifUnknown2, ifAnonymousMethod); TIntfFlagsEx = set of TIntfFlagEx; {$M+} IFoo = interface ['{35CFB4E2-4A13-48E9-8026-C1558001F4B7}'] procedure Main; end; {$M-} {$M+} IBar = interface(TProc) ['{AB2FEC1A-339F-4E58-B3DB-EC7B734F461B}'] end; {$M-} {$M+} TMyProc = reference to procedure; {$M-} procedure PrintIntf(typeInfo: Pointer); var context: TRttiContext; rttiInterface: TRttiInterfaceType; flags: TIntfFlagsEx; begin rttiInterface := context.GetType(typeInfo) as TRttiInterfaceType; flags := TIntfFlagsEx(rttiInterface.IntfFlags); Writeln(rttiInterface.Name, ' ', TValue.From(flags).ToString); end; begin PrintIntf(TypeInfo(IInterface)); PrintIntf(TypeInfo(IInvokable)); PrintIntf(TypeInfo(IFoo)); PrintIntf(TypeInfo(TProc)); PrintIntf(TypeInfo(TFunc<Integer>)); PrintIntf(TypeInfo(TMyProc)); PrintIntf(TypeInfo(IBar)); Readln; end. prints this: IInterface [ifHasGuid] IInvokable [ifMethodInfo] IFoo [ifHasGuid,ifMethodInfo] TProc [ifAnonymousMethod] TFunc<System.Integer> [ifAnonymousMethod] TMyProc [ifMethodInfo,ifAnonymousMethod] IBar [ifHasGuid,ifMethodInfo,ifAnonymousMethod] Edited June 5, 2019 by Stefan Glienke Share this post Link to post
Der schöne Günther 316 Posted June 5, 2019 I wonder where this value actually comes from. I guess not from RTL code that exists as a .pas file? Share this post Link to post
Stefan Glienke 2002 Posted June 5, 2019 3 minutes ago, Der schöne Günther said: I wonder where this value actually comes from. I guess not from RTL code that exists as a .pas file? The compiler is responsible for writing typeInfo into the binary. 1 Share this post Link to post
Remy Lebeau 1396 Posted June 5, 2019 (edited) 49 minutes ago, Stefan Glienke said: It seems indeed as if the TIntfFlag enum was never extended since Delphi6 (I think that was when interface RTTI was introduced) - I can confirm that at least since XE an interface type with $M+ gets a fourth flag (lets call it ifHasMethodInfo) set. If the type is an anonymous method type (see https://stackoverflow.com/q/49950534/587106) then there is a 7th enum value in the set. The situations where bit 5 and 6 are set are unknown to me. OK. Quote You might want to file an issue in QP about this. https://quality.embarcadero.com/browse/RSP-24631 Quote @Remy Lebeau Your diagnosis is still wrong - if the debugger shows [(out of bound) 3] then that means it has the 4th bit set. I'm aware of that. But that is not the exact text you originally showed, which is why I questioned it. Edited June 5, 2019 by Remy Lebeau Share this post Link to post
Stefan Glienke 2002 Posted June 5, 2019 22 minutes ago, Remy Lebeau said: But that is not the exact text you originally showed. If with "you" you mean @Der schöne Günther then yes. Share this post Link to post
Remy Lebeau 1396 Posted June 5, 2019 (edited) 12 minutes ago, Stefan Glienke said: If with "you" you mean @Der schöne Günther then yes. Yes, sorry, that is what I meant. Edited June 5, 2019 by Remy Lebeau Share this post Link to post