[fpc-devel] RTTI interface & variant late binding issue (mORMot)

Steve Hildebrandt Steve.Kassel at web.de
Mon Apr 13 14:21:56 CEST 2015



Am 13.04.2015 um 12:02 schrieb Steve Hildebrandt:
>
>
> Am 13.04.2015 um 09:38 schrieb Alfred:
>> Please do include me !
>> I have included the rtti-patch (diff) based on the current (today : 
>> 30566) trunk.
>> Its nothing else than the patch-set from Steve, but with one change:
>> for k:=0 to def.paras.count-1 do
>> begin
>>     para:=tparavarsym(def.paras[k]);
>>     {note from Alf:}
>>     {this was in the first patch set by Steve}
>>     {left out by Steve in the current patch}
>>     {?}
>>     {
>>     if (vo_is_hidden_para in para.varoptions) and not
>>        (vo_is_self in para.varoptions) then
>>        continue;
>>     }
>> Thanks, Alf.
> This was made, when I started actually using the generated RTTI.
> It was kind of problematic to invoke a method, if you have no 
> information how to pass the self parameter along.
>
> mfg Steve
I think something got mixed up here.
I got confused and didn't look into things properly, sorry.
The Patches are alright as they are, but the unified diff seems incorrect.

+                    if (vo_is_hidden_para in para.varoptions) and not
+                       (vo_is_self in para.varoptions) then
+                      continue;

should be included see "[PATCH 2/6] Added base for Reg/Off calculation 
to paramgr"

I've also attached a simple test.
If you would rather have a unified diff, I can provide it.

mfg Steve
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20150413/db911f3f/attachment.html>
-------------- next part --------------
program TestInterfaceRTTI;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  classes, typinfo, variants;

type
  TNumber = integer;
  TNewNumber = type integer;
  TIntegerArray = array of integer;
  TNormalClass = class(TObject);
  TSetOfByte = set of byte;
  TEnum = (enOne, enTwo, enThree);

  IMyNewMPInterface = interface['{AA503475-0187-4108-8E27-41475F4EF818}']
    procedure TestRegister(A: integer; var B: string); register;
    procedure TestStdCall(LongParaName: TObject; const B: string; var C: integer; out D: byte); stdcall;
    procedure TestSafeCall(out R: integer); safecall;
    function Number: TNumber; cdecl;
    function NewNumber: TNewNumber; cdecl;
    function AsString: string; pascal;
    function AsString2: string; safecall;
    procedure A2(const A: TIntegerArray);
    procedure OkParam1(Value: TSetOfByte);
    procedure OkParam2(Value: TEnum);
    procedure OkParam3(Value: Variant);
    procedure OkParam4(Value: TNormalClass);
    function OkReturn1: shortstring;
    function OkReturn2: TObject;
    function OkReturn3: IInterface;
    function OkReturn4: TSetOfByte;
    function OkReturn5: TNormalClass;
    function OkReturn6: TEnum;
    function OkReturn7: TClass;
    function OkReturn8: Pointer;
    function OkReturn9: PChar;
    function OkReturn10: TIntegerArray;
  end;

function aligntoptr(p : pointer) : pointer;inline;
begin
{$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
   result:=align(p,sizeof(p));
{$else FPC_REQUIRES_PROPER_ALIGNMENT}
   result:=p;
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
end;

function Skip(Value: PShortstring): pointer; overload;
begin
  Result := Value;
  Inc(PChar(Result), SizeOf(Value^[0]) + Length(Value^));
  Result:=aligntoptr(result);
end;

function checkParam(
  var p : Pointer;
  const aName : ShortString;
  aFlags : TParamFlags;
  aType  : PTypeInfo;
  aReg   : Byte;
  aOff   : LongInt) : Boolean;
var
  localp:pointer;
begin
  localp:=p;
  with PVmtMethodParam(p)^ do
    begin
      if aFlags <> Flags then
        exit(false);

      inc(localp,SizeOf(TParamFlags));
      localp:=aligntoptr(localp);


      //if aType <> ParamType then
      if aType <> PTypeInfo(ppointer(localp)^) then
        exit(false);

      inc(localp,SizeOf(PTypeInfo));

      //if aReg <> ParReg then
      if aReg <> PByte(localp)^ then
         exit(false);

      inc(localp,SizeOf(Byte));

      //if aOff <> ParOff then
      if aOff <> PLongInt(localp)^ then
         exit(false);

      inc(localp,SizeOf(LongInt));

      //if aName <> Name then
      if aName <> PShortString(localp)^ then
        exit(false);

      //p := Skip(@Name);
      Inc(PChar(localp), SizeOf(PShortString(localp)^[0]) + Length(PShortString(localp)^));
      p:=localp;

    end;

  result := true;
end;

function checkMethod(
  var p : Pointer;
  const aName : ShortString;
  aMethodCC   : TCallConv;
  aResultType : PTypeInfo;
  aStackSize  : Word;
  paramNames : array of ShortString;
  paramFlags : array of TParamFlags;
  paramTypes : array of PTypeInfo;
  paramReg   : array of Byte;
  paramOff   : array of LongInt) : Boolean;
var
  I : SizeInt;
begin
  if aName <> PIntfMethodEntry(p)^.Name then
    exit(false);

  //p := Skip(@PIntfMethodEntry(p)^.Name); // skip does not allign correct here !?
  Inc(PChar(p), SizeOf(PShortString(p)^[0]) + Length(PShortString(p)^));

  if 3 <> PByte(p)^ then
    exit(false);

  inc(p, sizeOf(Byte));

  if aMethodCC <> PCallConv(p)^ then
    exit(false);

  inc(p, sizeOf(TCallConv));

  if aResultType <> PPTypeInfo(p)^ then
    exit(false);

  inc(p, sizeOf(PTypeInfo));

  if aStackSize <> PWord(p)^ then
     exit(false);

  inc(p, sizeOf(Word));

  if length(paramNames) <> PByte(p)^ then
    exit(false);

  inc(p, sizeOf(Byte));

  for I := 0 to high(paramNames) do
    if not checkParam(p, paramNames[I], paramFlags[I], paramTypes[I], paramReg[I], paramOff[I]) then
      exit(false);

  result := true;
end;

function getMethodIntfTable(aTypeInfo : PTypeInfo) : PIntfMethodTable;
var
  td : PTypeData;
  p : Pointer;

  propCount : SmallInt;
  I : SizeInt;
begin
  td := GetTypeData(aTypeInfo);

  if aTypeInfo^.Kind = tkInterface then
    p := skip(@td^.IntfUnit)
  else
    p := skip(@td^.IIDStr);


  propCount := PSmallInt(p)^;

  inc(p, sizeOf(SmallInt));
  p:=aligntoptr(p);

  for I := 0 to propCount - 1 do
  begin
    p := skip(@(PPropInfo(p)^.Name));
  end;

  result := p;
end;

var
  count : SizeInt;
  p : Pointer;
begin
  p := getMethodIntfTable(TypeInfo(IMyNewMPInterface));
  count := PIntfMethodTable(p)^.Count;

  if count <> 22 then
    halt(-1);

  inc(p, SizeOf(TIntfMethodTable));

  //procedure TestRegister(A: integer; var B: string); register;
  if not checkMethod(p, 'TestRegister',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    nil,
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self','A','B'],
    [[TParamFlag.pfAddress],[],[TParamFlag.pfVar]],
    [TypeInfo(IMyNewMPInterface), TypeInfo(Integer), TypeInfo(String)],
    {$IFDEF CPUi386}[0, 1, 2]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 1, 2]{$ENDIF CPUARM}
    {$IFDEF win64}[0, 1, 2]{$ENDIF win64}
    ,
    {$IFDEF CPUi386}[0, 0, 0]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 0, 0]{$ENDIF CPUARM}
    {$IFDEF win64}[0, 0, 0]{$ENDIF win64}
  ) then
    halt(-2);

  //procedure TestStdCall(LongParaName: TObject; const B: string; var C: integer; out D: byte); stdcall;
  if not checkMethod(p, 'TestStdCall', TCallConv.ccStdCall, nil,
    {$IFDEF CPUi386}20{$ENDIF CPUi386}
    {$IFDEF CPUARM}4{$ENDIF CPUARM}
    {$IFDEF win64}40{$ENDIF win64},
    ['$self','LongParaName','B', 'C', 'D'],
    [[TParamFlag.pfAddress],[TParamFlag.pfAddress],[TParamFlag.pfConst],[TParamFlag.pfVar],[TParamFlag.pfOut]],
    [TypeInfo(IMyNewMPInterface), TypeInfo(TObject), TypeInfo(string), TypeInfo(integer), TypeInfo(byte)],
    {$IFDEF CPUi386}[255, 255, 255, 255, 255]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 1, 2, 3, 255]{$ENDIF CPUARM}
    {$IFDEF win64}[0, 1, 2, 3, 255]{$ENDIF win64}
    ,
    {$IFDEF CPUi386}[0, 4, 8, 12, 16]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 0, 0, 0, 0]{$ENDIF CPUARM}
    {$IFDEF win64}[0, 0, 0, 0, 32]{$ENDIF win64}
  ) then
    halt(-2);
  //procedure TestSafeCall(out R: integer); safecall;
  if not checkMethod(p, 'TestSafeCall', TCallConv.ccSafeCall, nil,
    {$IFDEF CPUi386}8{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self','R'],
    [[TParamFlag.pfAddress],[TParamFlag.pfOut]],
    [TypeInfo(IMyNewMPInterface), TypeInfo(integer)],
    {$IFDEF CPUi386}[255, 255]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 1]{$ENDIF CPUARM}
    {$IFDEF win64}[0, 1]{$ENDIF win64}
    ,
    {$IFDEF CPUi386}[0, 4]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 0]{$ENDIF CPUARM}
    {$IFDEF win64}[0, 0]{$ENDIF win64}
  ) then
    halt(-3);

  //function Number: TNumber; cdecl;
  if not checkMethod(p, 'Number', TCallConv.ccCdecl, TypeInfo(TNumber),
    {$IFDEF CPUi386}4{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    {$IFDEF CPUi386}[255]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF win64}[0]{$ENDIF win64}
    ,
    {$IFDEF CPUi386}[0]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF win64}[0]{$ENDIF win64}
  ) then
    halt(-4);

  //function NewNumber: TNewNumber; cdecl;
  if not checkMethod(p, 'NewNumber', TCallConv.ccCdecl, TypeInfo(TNewNumber),
    {$IFDEF CPUi386}4{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    {$IFDEF CPUi386}[255]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF win64}[0]{$ENDIF win64}
    ,
    {$IFDEF CPUi386}[0]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF win64}[0]{$ENDIF win64}
  ) then
    halt(-5);
  //function AsString: string; pascal;
  if not checkMethod(p, 'AsString',
    {$IFDEF CPUi386}TCallConv.ccPascal{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccStdCall{$ENDIF win64},
    TypeInfo(String),
    {$IFDEF CPUi386}8{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    {$IFDEF CPUi386}[255]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF win64}[0]{$ENDIF win64},

    {$IFDEF CPUi386}[4]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF win64}[0]{$ENDIF win64}
  ) then
    halt(-6);
  //function AsString2: string; safecall;
  if not checkMethod(p, 'AsString2', TCallConv.ccSafeCall, TypeInfo(String),
    {$IFDEF CPUi386}8{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    {$IFDEF CPUi386}[255]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF win64}[0]{$ENDIF win64}
    ,
    {$IFDEF CPUi386}[0]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF win64}[0]{$ENDIF win64}
  ) then
    halt(-7);
  //procedure A2(const A: TIntegerArray);
  if not checkMethod(p, 'A2',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    nil,
    {$IFDEF CPUi386}4{$ENDIF CPUi386}
    {$IFDEF CPUARM}4{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self', 'A'],
    [[TParamFlag.pfAddress], [TParamFlag.pfConst]],
    [TypeInfo(IMyNewMPInterface), TypeInfo(TIntegerArray)],
    {$IFDEF CPUi386}[0, 255]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 255]{$ENDIF CPUARM}
    {$IFDEF win64}[0, 1]{$ENDIF win64}
    ,
    {$IFDEF CPUi386}[0, 0]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 0]{$ENDIF CPUARM}
    {$IFDEF win64}[0, 0]{$ENDIF win64}
  ) then
    halt(-8);
  //procedure OkParam1(Value: TSetOfByte);
  if not checkMethod(p, 'OkParam1',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    nil,
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self', 'Value'],
    [[TParamFlag.pfAddress], []],
    [TypeInfo(IMyNewMPInterface), TypeInfo(TSetOfByte)],
    [0, 1],
    [0, 0]
  ) then
    halt(-9);
  //procedure OkParam2(Value: TEnum);
  if not checkMethod(p, 'OkParam2',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    nil,
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self', 'Value'],
    [[TParamFlag.pfAddress], []],
    [TypeInfo(IMyNewMPInterface), TypeInfo(TEnum)],
    [0, 1],
    [0, 0]
  ) then
    halt(-10);
  //procedure OkParam3(Value: Variant);
  if not checkMethod(p, 'OkParam3',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    nil,
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self', 'Value'],
    [[TParamFlag.pfAddress], []],
    [TypeInfo(IMyNewMPInterface), TypeInfo(Variant)],
    [0, 1],
    [0, 0]
  ) then
    halt(-11);
  //procedure OkParam4(Value: TNormalClass);
  if not checkMethod(p, 'OkParam4',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    nil,
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self', 'Value'],
    [[TParamFlag.pfAddress], [TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface), TypeInfo(TNormalClass)],
    [0, 1],
    [0, 0]
  ) then
    halt(-12);
  //function OkReturn1: shortstring;
  if not checkMethod(p, 'OkReturn1',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    TypeInfo(shortstring),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    [0],
    [0]
  ) then
    halt(-13);
  //function OkReturn2: TObject;
  if not checkMethod(p, 'OkReturn2',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    TypeInfo(TObject),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    [0],
    [0]
  ) then
    halt(-14);
  //function OkReturn3: IInterface;
  if not checkMethod(p, 'OkReturn3',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    TypeInfo(IInterface),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    [0],
    [0]
  ) then
    halt(-15);
  //function OkReturn4: TSetOfByte;
  if not checkMethod(p, 'OkReturn4',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    TypeInfo(TSetOfByte),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    [0],
    [0]
  ) then
    halt(-16);
  //function OkReturn5: TNormalClass;
  if not checkMethod(p, 'OkReturn5',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    TypeInfo(TNormalClass),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    [0],
    [0]
  ) then
    halt(-17);
  //function OkReturn6: TEnum;
  if not checkMethod(p, 'OkReturn6',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    TypeInfo(TEnum),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    [0],
    [0]
  ) then
    halt(-18);
  //function OkReturn7: TClass;
  if not checkMethod(p, 'OkReturn7',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    TypeInfo(TClass),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    [0],
    [0]
  ) then
    halt(-19);
  //function OkReturn8: Pointer;
  if not checkMethod(p, 'OkReturn8',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    TypeInfo(Pointer),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    [0],
    [0]
  ) then
    halt(-20);
  //function OkReturn9: PChar;
  if not checkMethod(p, 'OkReturn9',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    TypeInfo(PChar),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    [0],
    [0]
  ) then
    halt(-21);
  //function OkReturn10: TIntegerArray;
  if not checkMethod(p, 'OkReturn10',
    {$IFDEF CPUi386}TCallConv.ccReg{$ENDIF CPUi386}
    {$IFDEF CPUARM}TCallConv.ccStdCall{$ENDIF CPUARM}
    {$IFDEF win64}TCallConv.ccReg{$ENDIF win64},
    TypeInfo(TIntegerArray),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF win64}32{$ENDIF win64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    [0],
    [0]
  ) then
    halt(-22);

  writeln('Sucess!');
  readln;
end.


More information about the fpc-devel mailing list