123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- program trtti15;
- {$mode objfpc}{$H+}
- uses
- typinfo,
- sysutils;
- type
- IBlubb = interface
- procedure Test;
- end;
- {$push}
- {$M+}
- ITest = interface
- procedure Test;
- function Test2: LongInt;
- procedure Test3(arg1: LongInt; arg2: String);
- function Test4(arg1: LongInt; arg2: String): String;
- function Test5(arg1: array of LongInt; arg2: Int64): Int64;
- function Test6(arg1: LongInt; arg2: String): String; stdcall;
- {$if defined(CPUI386) or defined(CPUI8086)}
- function Test7(arg1: LongInt; arg2: String): String; pascal;
- {$endif}
- function Test8(arg1: LongInt; arg2: String): String; cdecl;
- procedure Test9(var arg1; out arg2; constref arg3);
- property T: LongInt read Test2;
- property T2: LongInt read Test2;
- end;
- {$interfaces corba}
- ITestRaw = interface
- ['Test']
- function Test: LongInt;
- property T: LongInt read Test;
- end;
- {$pop}
- procedure ErrorHalt(const aMsg: String; const aArgs: array of const);
- begin
- if Length(aArgs) = 0 then
- Writeln(aMsg)
- else
- Writeln(Format(aMsg, aArgs));
- Halt(1);
- end;
- procedure TestParam(aParam: PVmtMethodParam; const aName: String; aFlags: TParamFlags; aTypeInfo: PTypeInfo);
- begin
- Writeln(#9'Testing parameter ', aName);
- if not (pfHidden in aFlags) and (aParam^.Name <> aName) then
- ErrorHalt('Expected parameter name %s, but got %s', [aName, aParam^.Name]);
- if aParam^.Flags <> aFlags then
- ErrorHalt('Expected parameter flags %s, but got %s', [HexStr(Word(aFlags), 4), HexStr(Word(aParam^.Flags), 4)]);
- if Assigned(aTypeInfo) then begin
- if not Assigned(aParam^.ParamType) then
- ErrorHalt('Expected parameter type %s, but got Nil', [aTypeInfo^.Name]);
- if aParam^.ParamType^ <> aTypeInfo then
- ErrorHalt('Expected parameter type %s, but got %s', [aTypeInfo^.Name, aParam^.ParamType^^.Name]);
- end else begin
- if Assigned(aParam^.ParamType) then
- ErrorHalt('Expected Nil parameter type, but got %s', [aParam^.ParamType^^.Name])
- end;
- end;
- type
- TTestParam = record
- name: String;
- flags: TParamFlags;
- paramtype: PTypeInfo;
- end;
- function MakeParam(const aName: String; aFlags: TParamFlags; aTypeInfo: PTypeInfo): TTestParam;
- begin
- Result.name := aName;
- Result.flags := aFlags;
- Result.paramtype := aTypeInfo;
- end;
- procedure TestMethod(aMethod: PIntfMethodEntry; const aName: String; aKind: TMethodKind; aCC: TCallConv; aParams: array of TTestParam; aResult: PTypeInfo);
- var
- c, i: LongInt;
- param: PVmtMethodParam;
- begin
- Writeln('Testing method ', aName);
- if aMethod^.Name <> aName then
- ErrorHalt('Expected method name %s, but got %s', [aName, aMethod^.Name]);
- if aMethod^.CC <> aCC then
- ErrorHalt('Expected calling convention %d, but got %d', [Ord(aCC), Ord(aMethod^.CC)]);
- if aMethod^.Kind <> aKind then
- ErrorHalt('Expected method kind %d, but got %d', [Ord(aKind), Ord(aMethod^.Kind)]);
- if Assigned(aResult) and not Assigned(aMethod^.ResultType) then
- ErrorHalt('Expected result type %s, but got Nil', [aResult^.Name]);
- if Assigned(aResult) and (aResult <> aMethod^.ResultType^) then
- ErrorHalt('Expected result type %s, but got %s', [aResult^.Name, aMethod^.ResultType^^.Name]);
- { we ignore an eventual result parameter }
- if aMethod^.ParamCount < Length(aParams) then
- ErrorHalt('Expected at least %d parameters, but got %d', [Length(aParams), aMethod^.ParamCount]);
- if aMethod^.ParamCount < 1 then
- ErrorHalt('Expected at least 1 parameter, but got 0', []);
- { first parameter is always self }
- c := 1;
- TestParam(aMethod^.Param[0], aParams[0].name, aParams[0].flags, aParams[0].paramtype);
- for i := 1 to aMethod^.ParamCount - 1 do begin
- param := aMethod^.Param[i];
- if pfResult in param^.Flags then
- Continue;
- TestParam(param, aParams[c].name, aParams[c].flags, aParams[c].paramtype);
- Inc(c);
- end;
- if c <> Length(aParams) then
- ErrorHalt('Expected %d parameters, but got %d', [Length(aParams), c]);
- end;
- type
- TTestMethod = record
- name: String;
- cc: TCallConv;
- kind: TMethodKind;
- result: PTypeInfo;
- params: array of TTestParam;
- end;
- function MakeMethod(const aName: String; aCC: TCallConv; aKind: TMethodKind; aResult: PTypeInfo; aParams: array of TTestParam): TTestMethod;
- var
- i: LongInt;
- begin
- Result.name := aName;
- Result.cc := aCC;
- Result.kind := aKind;
- Result.result := aResult;
- SetLength(Result.params, Length(aParams));
- for i := Low(aParams) to High(aParams) do
- Result.params[i - Low(aParams)] := aParams[i];
- end;
- procedure TestInterface(aIntf: PTypeData; aRaw: Boolean; aIIDStr: String; aPropCount: LongInt; aMethods: array of TTestMethod);
- var
- proptable: PPropData;
- methtable: PIntfMethodTable;
- i: LongInt;
- begin
- if aRaw then begin
- proptable := PInterfaceRawData(aIntf)^.PropertyTable;
- methtable := PInterfaceRawData(aIntf)^.MethodTable;
- if PInterfaceRawData(aIntf)^.IIDStr <> aIIDStr then
- ErrorHalt('Expected IIDStr ''%s'', but got ''%s''', [aIIDStr, PInterfaceRawData(aIntf)^.IIDStr]);
- end else begin
- proptable := PInterfaceData(aIntf)^.PropertyTable;
- methtable := PInterfaceData(aIntf)^.MethodTable;
- end;
- if proptable^.PropCount <> aPropCount then
- ErrorHalt('Expected %d properties, but got %d', [aPropCount, proptable^.PropCount]);
- if methtable^.Count <> Length(aMethods) then
- ErrorHalt('Expected %d methods, but got %d', [Length(aMethods), methtable^.Count]);
- if methtable^.RttiCount = $ffff then
- Exit;
- for i := 0 to methtable^.Count - 1 do begin
- TestMethod(methtable^.Method[i], aMethods[i].name, aMethods[i].kind, aMethods[i].cc, aMethods[i].params, aMethods[i].result);
- end;
- end;
- const
- {$if defined(CPUI386) or defined(CPUI8086) or defined(CPUX86_64) or defined(CPUM68K)}
- DefaultCallingConvention = ccReg;
- {$else}
- DefaultCallingConvention = ccStdCall;
- {$endif}
- begin
- Writeln('Testing interface ITestRaw');
- { raw interfaces don't support $M+ currently }
- TestInterface(GetTypeData(TypeInfo(ITestRaw)), True, 'Test', 0{1}, [
- MakeMethod('Test', ccReg, mkFunction, TypeInfo(LongInt), [])
- ]);
- Writeln('Testing interface ITest');
- TestInterface(GetTypeData(TypeInfo(ITest)), False, '', 2, [
- MakeMethod('Test', DefaultCallingConvention, mkProcedure, Nil, [
- MakeParam('$self', [pfHidden, pfSelf, pfAddress], TypeInfo(ITest))
- ]),
- MakeMethod('Test2', DefaultCallingConvention, mkFunction, TypeInfo(LongInt), [
- MakeParam('$self', [pfHidden, pfSelf, pfAddress], TypeInfo(ITest))
- ]),
- MakeMethod('Test3', DefaultCallingConvention, mkProcedure, Nil, [
- MakeParam('$self', [pfHidden, pfSelf, pfAddress], TypeInfo(ITest)),
- MakeParam('arg1', [], TypeInfo(LongInt)),
- MakeParam('arg2', [], TypeInfo(String))
- ]),
- MakeMethod('Test4', DefaultCallingConvention, mkFunction, TypeInfo(String), [
- MakeParam('$self', [pfHidden, pfSelf, pfAddress], TypeInfo(ITest)),
- MakeParam('arg1', [], TypeInfo(LongInt)),
- MakeParam('arg2', [], TypeInfo(String))
- ]),
- MakeMethod('Test5', DefaultCallingConvention, mkFunction, TypeInfo(Int64), [
- MakeParam('$self', [pfHidden, pfSelf, pfAddress], TypeInfo(ITest)),
- MakeParam('arg1', [pfArray, pfReference], TypeInfo(LongInt)),
- MakeParam('$highARG1', [pfHidden, pfHigh, pfConst], TypeInfo(SizeInt)),
- MakeParam('arg2', [], TypeInfo(Int64))
- ]),
- MakeMethod('Test6', ccStdCall, mkFunction, TypeInfo(String), [
- MakeParam('$self', [pfHidden, pfSelf, pfAddress], TypeInfo(ITest)),
- MakeParam('arg1', [], TypeInfo(LongInt)),
- MakeParam('arg2', [], TypeInfo(String))
- ]),
- {$if defined(CPUI386) or defined(CPUI8086)}
- MakeMethod('Test7', ccPascal, mkFunction, TypeInfo(String), [
- MakeParam('$self', [pfHidden, pfSelf, pfAddress], TypeInfo(ITest)),
- MakeParam('arg1', [], TypeInfo(LongInt)),
- MakeParam('arg2', [], TypeInfo(String))
- ]),
- {$endif}
- MakeMethod('Test8', ccCdecl, mkFunction, TypeInfo(String), [
- MakeParam('$self', [pfHidden, pfSelf, pfAddress], TypeInfo(ITest)),
- MakeParam('arg1', [], TypeInfo(LongInt)),
- MakeParam('arg2', [], TypeInfo(String))
- ]),
- MakeMethod('Test9', DefaultCallingConvention, mkProcedure, Nil, [
- MakeParam('$self', [pfHidden, pfSelf, pfAddress], TypeInfo(ITest)),
- MakeParam('arg1', [pfVar], Nil),
- MakeParam('arg2', [pfOut], Nil),
- MakeParam('arg3', [pfConstRef], Nil)
- ])
- ]);
- end.
|