Strange TypeInfo behavior by anonymous methods

For a piece of code that requires a type of "family" of a universal type, I am trying to use it TypeInfoto get the necessary information.

class function GetTypeKind<T>:TTypeKind;

For most types, I can figure it out. But the type of anonymous method behaves unexpectedly.

I have an anonymous method type defined as:

TMethodProc = reference to procedure;

And I'm trying to get type information:

MyKind := GetTypeKind<TMethodProc>;

class function GetTypeKind<T>:TTypeKind;
var 
  TI: PTypeInfo;
begin
  TI := TypeInfo(T);

  ...
end;

I know that anonymous methods hide compiler magic. But I get the following result:

TI.TypeData.IntfParent == IInterface
TI.TypeData.IntfFlags == [(out of bounds)6]

Flags have an unexpected meaning, TIntfFlaghas three meanings, so 6 is unexpected. The GUID is also not a guid. It has a repeating set of the same 8 bytes, mostly 00. For example (0, 225, 48, 180, 0, 0, 0, 0, 0, 225, 48, 180, 0, 0, 0, 0)

TypeInfo .

, () 6 - ?

+6
1

.

, , Invoke() , . TTypeKind tkInterface IntfParent IInterface.

, , Invoke().

?

IntfFlags - TIntfFlagsBase, Set TIntfFlag TIntfFlag:

TIntfFlag = (ifHasGuid, ifDispInterface, ifDispatch);

ifHasGuid
GUID ( ).

ifDispInterface
.

ifDispatch
.

Set - . . TIntfFlagsBase ifHasGuid - 0, ifDispInterface - 1, ifDispatch - 2. , 6 (110b) ifDispatch ifDispInterface ifDispatch, ifHasGuid. , IntfGuid , TTypeData .


: XE2, , , , IntfFlags 64 (TIntfFlag(6), ) 6, . , , , , , , Guid ( ).


: , , ( {$M+}) , TIntfFlag. :

RSP-24631: System.TypInfo.TIntfFlag

TIntfFlag(6) .

" " IInvokable? :

, , TIntfFlag Delphi6 ( , , RTTI) - , , , XE $M+ ( ifHasMethodInfo) .

... . , 5 6, .

...

:

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.

:

IInterface [ifHasGuid]
IInvokable [ifMethodInfo]
IFoo [ifHasGuid,ifMethodInfo]
TProc [ifAnonymousMethod]
TFunc [ifAnonymousMethod]
TMyProc [ifMethodInfo,ifAnonymousMethod]
IBar [ifHasGuid,ifMethodInfo,ifAnonymousMethod]
+4
source

Source: https://habr.com/ru/post/1696372/


All Articles