[fpc-pascal] TParamFlags and fpc 3.2.0.

Sven Barth pascaldragon at googlemail.com
Sat Jul 27 23:18:41 CEST 2019


Am 27.07.2019 um 19:02 schrieb fredvs:
> Imho, it seems that in your code  "if not (pfHidden in flags) then" was
> placed one "end;" too far.
That's what I meant in the mail you replied to.

Am 27.07.2019 um 19:07 schrieb fredvs:
> Sven, did you try a simple code, it seems that "$self" first parameter is
> always added into params list, even if you filter it with "pfHidden" flag.
This example works as intended:

=== code begin ===

program tmethodinfo;

{$mode objfpc}{$H+}

uses
   typinfo, classes, sysutils;

{$M+}
type
   TMyMethod1 = procedure(const aSender: TObject) of object;
   TMyMethod2 = function(var aArg: LongInt; aArr: array of LongInt): 
String of object;
{$M-}

function FuncToString(aTI: PTypeInfo): String;
var
   td: PTypeData;
   pb: PByte;
   args: TStrings;
   flags: TParamFlags;
   res, s, prefix, argname, argtype: String;
   i: SizeInt;
begin
   if aTI^.Kind <> tkMethod then
     raise Exception.Create('Method type information expected');

   td := GetTypeData(aTI);
   args := TStringList.Create;
   try
     args.Delimiter := ';';
     args.QuoteChar := #0;

     pb := @td^.ParamList;
     for i := 0 to td^.ParamCount - 1 do begin
       flags := TParamFlags(PWord(pb)^);
       Inc(pb, SizeOf(TParamFlags));
       argname := PShortString(pb)^;
       Inc(pb, SizeOf(Byte) + Length(argname));
       argtype := PShortString(pb)^;
       Inc(pb, SizeOf(Byte) + Length(argtype));
       if pfHidden in flags then
         Continue;
       prefix := '';
       if pfConst in flags then
         prefix := 'const'
       else if pfConstRef in flags then
         prefix := 'constref'
       else if pfVar in flags then
         prefix := 'var'
       else if pfOut in flags then
         prefix := 'out';
       s := '';
       if prefix <> '' then
         s := prefix + ' ';
       s := s + argname + ': ';
       if pfArray in flags then
         s := s + 'array of ';
       s := s + argtype;
       args.Add(s);
     end;
     if td^.MethodKind in [mkFunction, mkClassFunction] then
       res := PShortString(pb)^
     else
       res := '';

     Result := '';
     if td^.MethodKind in [mkClassFunction, mkClassProcedure, 
mkClassConstructor, mkClassDestructor] then
       Result := 'class ';
     if td^.MethodKind in [mkClassFunction, mkFunction] then
       Result := Result + 'function '
     else if td^.MethodKind in [mkClassProcedure, mkProcedure] then
       Result := Result + 'procedure '
     else if td^.MethodKind in [mkConstructor, mkClassConstructor] then
       Result := Result + 'constructor '
     else if td^.MethodKind in [mkDestructor, mkClassDestructor] then
       Result := Result + 'destructor '
     else
       Result := Result + 'unknown ';
     Result := Result + aTI^.Name + ' ';
     if args.Count > 0 then
       Result := Result + '(' + args.DelimitedText + ')';
     if res <> '' then
       Result := Result + ': ' + res;
   finally
     args.Free;
   end;
end;

begin
   Writeln(FuncToString(TypeInfo(TMyMethod1)));
   Writeln(FuncToString(TypeInfo(TMyMethod2)));
end.

=== code end ===

And will print the following:

=== code begin ===

procedure TMyMethod1 ( const aSender: TObject )
function TMyMethod2 ( var aArg: LongInt ; aArr: array of LongInt ): 
AnsiString

=== code end ===

So it definitely works, now you only need to figure out the problem in 
your code.

Regards,
Sven


More information about the fpc-pascal mailing list