user401247
user401247

Reputation:

How to get details on procedure types in a record using rtti in Delphi

Given a Delphi record that contains procedure types as fields, for example:

TProcType1 = function (index : integer; value : double) : string;
TProcType2 = function (bValue : boolean; ptr : TPointer) : integer; 
TMyRecord = record
   proc1 : TProcType1;
   proc2 : TProcType2;
end

Is it possible to get hold of the detailed information on the procedure type signatures? eg that proc1 is declared as a procedure type with two arguments, integer and double, and a return type of string?

I can convert the procedure types field into a string using ToString on a field and parse it for the information, for example, using code such as:

 context := TRttiContext.Create;
 rtype := context.GetType(TypeInfo(TMyRecord));
 fields := rtype.GetFields;
 for i := 0 to High(fields) do
     begin
     astr := fields[i].FieldType.ToString;
     // parse astr to get info on procedure type
     end

I was wondering if there is any way to deconstruct the procedure types using rtti instead of having to manually parse to ToString? For normal method fields, this is possible.

I can guarantee that the record will only contain procedure type fields. Using Delphi 10.4

Upvotes: 2

Views: 1025

Answers (1)

Andreas Rejbrand
Andreas Rejbrand

Reputation: 108919

Yes, this is rather straightforward:

var
  Context: TRttiContext;
  RType: TRttiType;
  Field: TRttiField;
  p: TRttiProcedureType;
  param: TRttiParameter;
begin
  Context := TRttiContext.Create;
  RType := Context.GetType(TypeInfo(TMyRecord));
  for Field in RType.GetFields do
  begin
    if Field.FieldType is TRttiProcedureType then
    begin
      p := TRttiProcedureType(Field.FieldType);
      Writeln(p.Name);
      Writeln('Parameter count: ', Length(p.GetParameters));
      for param in p.GetParameters do
      begin
        Writeln('Parameter name: ', param.Name);
        if Assigned(param.ParamType) then
          Writeln('Parameter type: ', param.ParamType.ToString);
      end;
      if Assigned(p.ReturnType) then
        Writeln('Result type: ', p.ReturnType.ToString);
      Writeln;
    end;
  end;
end;

Output:

TProcType1
Parameter count: 2
Parameter name: index
Parameter type: Integer
Parameter name: value
Parameter type: Double
Result type: string

TProcType2
Parameter count: 2
Parameter name: bValue
Parameter type: Boolean
Parameter name: ptr
Parameter type: Pointer
Result type: Integer

TRttiParameter also has a Flags property which is a set that tells you the kind of the parameter (e.g. var or const or out).

TRttiProcedureType can also tell you the procedure's calling convention.

Upvotes: 2

Related Questions