3
votes

In the debate about the closing of the class helper loophole that allowed easy access to private members (fields and methods) of a class in Delphi 10.1 Berlin, it is often claimed that

  • extended RTTI allows access to the private members of a class that was compiled with (extended) RTTI enabled, and
  • all VCL/RTL/FMX classes have this enabled.

However, if I run this simple unit (a simple form with one TListBox, nothing else):

unit RttiAccessTest;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Rtti, Vcl.StdCtrls;

type
  TForm16 = class(TForm)
    ListBox1: TListBox;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form16: TForm16;

implementation

{$R *.dfm}

function GetMethodString(const MethodName: string): string;
var
  M: TRTTIMethod;
  I: Integer;
begin
  M := TRttiContext.Create.GetType(TCustomForm).GetMethod(MethodName);
  if Assigned(M) then
    Result := 'Method ' + MethodName + ': ''' + M.ToString + ';'''
  else
    Result := 'Method ' + MethodName + ' cannot be found';
end;

procedure TForm16.FormCreate(Sender: TObject);
begin
  Listbox1.Items.Add(GetMethodString('SetWindowState'));
  Listbox1.Items.Add(GetMethodString('ShowModal'));
end;

end.

The text in the list box is:

Method SetWindowState cannot be found 
Method ShowModal: 'function ShowModal: Integer;'

This means I cannot get access to this private method SetWindowState of TCustomForm. Is this because not all classes in the RTL/VCL/FMX have extended RTTI, or am I doing something wrong?

If I am doing something wrong or forgetting something, then what? In other words, what do I have to do to get RTTI access to, say, SetWindowState of TCustomForm? I cannot get this access in Seattle or earlier either.

Note

I know how to get access to the method anyway, using the fact that class helpers can still get the address of private methods, but that is not my question. I am particularly asking about how to do this with RTTI.

2
There was an identical question a couple of days ago, searching...LU RD
Found it: How to access the private method TStreamReader.FillBuffer in Delphi 10.1 Berlin?. Conclusion was that {$MethodInfo} is OFF by default in the RTL.LU RD
The METHODINFO was not enough, see my answer.LU RD
But there, the answer mentioned the class helper addres/method trick. Not how to od it with RTTI. Obviously, it is not possible with RTTI.Rudy Velthuis
private is private... see blog.marcocantu.com/blog/…cydo

2 Answers

3
votes

The obvious conclusion is that whilst this type is compiled with extended RTTI, that RTTI is not included for private methods.

1
votes

In order to access strict private/private methods with RTTI, use the compiler directive {$RTTI}.

Syntax

The general syntax of the $RTTI directive can be split into three parts. The basic form of $RTTI is as follows:

{$RTTI INHERIT|EXPLICIT [visibility-clause]}

visibility-clause:

METHODS|PROPERTIES|FIELDS (visibility-expression)

visibility-expression:

[vcPrivate],[vcProtected], [vcPublic], [vcPublished];

Example:

{$RTTI EXPLICIT METHODS([vcPublic, vcProtected, vcPrivate])}

Sets the visibility for public,protected and private methods

Note: The scope is local for this directive and the RTL/VCL/FMX have these options off, which means that access to protected/private methods with RTTI are not possible.