program TestInterfaceRTTI;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  classes, typinfo, variants,sysutils;

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;
begin
  with PVmtMethodParam(p)^ do
    begin
      if aName <> Name then
        exit(false);
      if aFlags <> Flags then
        exit(false);
      if aType <> ParamType then
        exit(false);
      if aReg <> ParReg then
        exit(false);
      if aOff <> ParOff then
        exit(false);
      p := Skip(@Name);
    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);

  //skip on ARM does not allign correct here !!?
  //p := Skip(@PIntfMethodEntry(p)^.Name);
  //p := Skip(p);
  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));
  // added !!
  p:=aligntoptr(p);

  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));
  // added !!
  p:=aligntoptr(p);

  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;

  writeln(aName+' Success !');
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);
  writeln('22 methods found !');

  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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64}
    ,nil,
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}[0, 1, 2]{$ENDIF CPUX86_64}
    ,
    {$IFDEF CPUi386}[0, 0, 0]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 0, 0]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}[0, 0, 0]{$ENDIF CPUX86_64}
  ) 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 CPUX86_64}{$IFDEF Windows}40{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}{$IFDEF Windows}[0, 1, 2, 3, 255]{$ELSE}[0, 1, 2, 3, 4]{$ENDIF Windows}{$ENDIF CPUX86_64}
    ,
    {$IFDEF CPUi386}[0, 4, 8, 12, 16]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 0, 0, 0, 0]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}[0, 0, 0, 0, 32]{$ELSE}[0, 0, 0, 0, 0]{$ENDIF Windows}{$ENDIF CPUX86_64}
  ) 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 CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$self','R'],
    [[TParamFlag.pfAddress],[TParamFlag.pfOut]],
    [TypeInfo(IMyNewMPInterface), TypeInfo(integer)],
    {$IFDEF CPUi386}[255, 255]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 1]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}[0, 1]{$ENDIF CPUX86_64}
    ,
    {$IFDEF CPUi386}[0, 4]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 0]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}[0, 0]{$ENDIF CPUX86_64}
  ) 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 CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    {$IFDEF CPUi386}[255]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}[0]{$ENDIF CPUX86_64}
    ,
    {$IFDEF CPUi386}[0]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}[0]{$ENDIF CPUX86_64}
  ) 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 CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    {$IFDEF CPUi386}[255]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}[0]{$ENDIF CPUX86_64}
    ,
    {$IFDEF CPUi386}[0]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}[0]{$ENDIF CPUX86_64}
  ) 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 CPUX86_64}TCallConv.ccStdCall{$ENDIF CPUX86_64},
    TypeInfo(String),
    {$IFDEF CPUi386}8{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    {$IFDEF CPUi386}[255]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}[0]{$ENDIF CPUX86_64},

    {$IFDEF CPUi386}[4]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}[0]{$ENDIF CPUX86_64}
  ) 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 CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    {$IFDEF CPUi386}[255]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}[0]{$ENDIF CPUX86_64}
    ,
    {$IFDEF CPUi386}[0]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}[0]{$ENDIF CPUX86_64}
  ) 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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    nil,
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$self', 'A'],
    [[TParamFlag.pfAddress], [TParamFlag.pfConst]],
    [TypeInfo(IMyNewMPInterface), TypeInfo(TIntegerArray)],
    {$IFDEF CPUi386}[0, 1]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 1]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}[0, 1]{$ENDIF CPUX86_64}
    ,
    {$IFDEF CPUi386}[0, 0]{$ENDIF CPUi386}
    {$IFDEF CPUARM}[0, 0]{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}[0, 0]{$ENDIF CPUX86_64}
  ) 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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    nil,
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    nil,
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    nil,
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    nil,
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    TypeInfo(shortstring),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    TypeInfo(TObject),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    TypeInfo(IInterface),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    TypeInfo(TSetOfByte),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    TypeInfo(TNormalClass),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    TypeInfo(TEnum),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    TypeInfo(TClass),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    TypeInfo(Pointer),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    TypeInfo(PChar),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$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 CPUX86_64}TCallConv.ccReg{$ENDIF CPUX86_64},
    TypeInfo(TIntegerArray),
    {$IFDEF CPUi386}0{$ENDIF CPUi386}
    {$IFDEF CPUARM}0{$ENDIF CPUARM}
    {$IFDEF CPUX86_64}{$IFDEF Windows}32{$ELSE}0{$ENDIF Windows}{$ENDIF CPUX86_64},
    ['$self'],
    [[TParamFlag.pfAddress]],
    [TypeInfo(IMyNewMPInterface)],
    [0],
    [0]
  ) then
    halt(-22);

  writeln();
  writeln('All Success !!!');
  writeln('Press key to end.');
  readln;
end.

