tests.rtti.impl.pas 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919
  1. unit Tests.Rtti.Impl;
  2. {$ifdef fpc}
  3. {$mode objfpc}{$H+}
  4. {$endif}
  5. {.$define debug}
  6. interface
  7. uses
  8. {$IFDEF FPC}
  9. fpcunit,testregistry, testutils,
  10. {$ELSE FPC}
  11. TestFramework,
  12. {$ENDIF FPC}
  13. sysutils, typinfo, Rtti,
  14. Tests.Rtti.Util;
  15. { Note: Delphi does not provide a CreateImplementation for TRttiInvokableType
  16. and its descendants, so these tests are disabled for Delphi }
  17. type
  18. TTestImpl = class(TTestCase)
  19. private
  20. InputArgs: array of TValue;
  21. OutputArgs: array of TValue;
  22. ResultValue: TValue;
  23. InOutMapping: array of SizeInt;
  24. InputUntypedTypes: array of PTypeInfo;
  25. InvokedMethodName: String;
  26. procedure OnHandleIntfMethod(aMethod: TRttiMethod; const aArgs: TValueArray; out aResult: TValue);
  27. procedure DoIntfImpl(aIntf: IInterface; aTypeInfo: PTypeInfo; aIndex: LongInt; aInputArgs, aOutputArgs: TValueArray; aInOutMapping: array of SizeInt; aResult: TValue);
  28. {$ifdef fpc}
  29. procedure OnHandleInvokable(aInvokable: TRttiInvokableType; const aArgs: TValueArray; out aResult: TValue);
  30. procedure DoMethodImpl(aTypeInfo: PTypeInfo; aInputArgs, aOutputArgs: TValueArray; aInOutMapping: array of SizeInt; aResult: TValue);
  31. procedure DoProcImpl(aTypeInfo: PTypeInfo; aInputArgs, aOutputArgs: TValueArray; aInOutMapping: array of SizeInt; aResult: TValue);
  32. {$ifndef InLazIDE}
  33. {$ifdef fpc}generic{$endif} procedure GenDoIntfImpl<T: IInterface>(aIntf: T; aIndex: LongInt; aInputArgs, aOutputArgs: TValueArray; aInOutMapping: array of SizeInt; aResult: TValue);
  34. {$ifdef fpc}generic{$endif} procedure GenDoMethodImpl<T>(aInputArgs, aOutputArgs: TValueArray; aInOutMapping: array of SizeInt; aResult: TValue);
  35. {$ifdef fpc}generic{$endif} procedure GenDoProcImpl<T>(aInputArgs, aOutputArgs: TValueArray; aInOutMapping: array of SizeInt; aResult: TValue);
  36. {$endif}
  37. {$endif}
  38. {$ifdef fpc}
  39. procedure Status(const aMsg: String); inline;
  40. procedure Status(const aMsg: String; const aArgs: array of const); inline;
  41. {$endif}
  42. published
  43. procedure TestIntfMethods;
  44. {$ifdef fpc}
  45. procedure TestMethodVars;
  46. procedure TestProcVars;
  47. {$endif}
  48. end;
  49. implementation
  50. type
  51. {$push}
  52. {$M+}
  53. ITestInterface = interface
  54. ['{1DE799BB-BEE9-405F-9AF3-D55DE978C793}']
  55. procedure TestMethod1;
  56. function TestMethod2(aArg1: SizeInt): SizeInt;
  57. procedure TestMethod3(aArg1: AnsiString);
  58. procedure TestMethod4(aArg1: ShortString);
  59. function TestMethod5: AnsiString;
  60. function TestMethod6: ShortString;
  61. procedure TestMethod7(aArg1: SizeInt; var aArg2: SizeInt; out aArg3: SizeInt; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: SizeInt);
  62. procedure TestMethod8(aArg1: AnsiString; var aArg2: AnsiString; out aArg3: AnsiString; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: AnsiString);
  63. procedure TestMethod9(aArg1: ShortString; var aArg2: ShortString; out aArg3: ShortString; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: ShortString);
  64. procedure TestMethod10(aArg1: Single; var aArg2: Single; out aArg3: Single; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Single);
  65. procedure TestMethod11(aArg1: Double; var aArg2: Double; out aArg3: Double; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Double);
  66. procedure TestMethod12(aArg1: Extended; var aArg2: Extended; out aArg3: Extended; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Extended);
  67. procedure TestMethod13(aArg1: Comp; var aArg2: Comp; out aArg3: Comp; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Comp);
  68. procedure TestMethod14(aArg1: Currency; var aArg2: Currency; out aArg3: Currency; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Currency);
  69. function TestMethod15(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: SizeInt): SizeInt;
  70. function TestMethod16(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Single): Single;
  71. function TestMethod17(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Double): Double;
  72. function TestMethod18(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Extended): Extended;
  73. function TestMethod19(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Comp): Comp;
  74. function TestMethod20(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Currency): Currency;
  75. procedure TestMethod21(var aArg1; out aArg2; const aArg3; {$ifdef fpc}constref{$else}const [ref]{$endif} aArg4);
  76. end;
  77. {$pop}
  78. TTestMethod1 = procedure of object;
  79. TTestMethod2 = function(aArg1: SizeInt): SizeInt of object;
  80. TTestMethod3 = procedure(aArg1: AnsiString) of object;
  81. TTestMethod4 = procedure(aArg1: ShortString) of object;
  82. TTestMethod5 = function: AnsiString of object;
  83. TTestMethod6 = function: ShortString of object;
  84. TTestMethod7 = procedure(aArg1: SizeInt; var aArg2: SizeInt; out aArg3: SizeInt; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: SizeInt) of object;
  85. TTestMethod8 = procedure(aArg1: AnsiString; var aArg2: AnsiString; out aArg3: AnsiString; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: AnsiString) of object;
  86. TTestMethod9 = procedure(aArg1: ShortString; var aArg2: ShortString; out aArg3: ShortString; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: ShortString) of object;
  87. TTestMethod10 = procedure(aArg1: Single; var aArg2: Single; out aArg3: Single; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Single) of object;
  88. TTestMethod11 = procedure(aArg1: Double; var aArg2: Double; out aArg3: Double; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Double) of object;
  89. TTestMethod12 = procedure(aArg1: Extended; var aArg2: Extended; out aArg3: Extended; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Extended) of object;
  90. TTestMethod13 = procedure(aArg1: Comp; var aArg2: Comp; out aArg3: Comp; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Comp) of object;
  91. TTestMethod14 = procedure(aArg1: Currency; var aArg2: Currency; out aArg3: Currency; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Currency) of object;
  92. TTestMethod15 = function(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: SizeInt): SizeInt of object;
  93. TTestMethod16 = function(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Single): Single of object;
  94. TTestMethod17 = function(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Double): Double of object;
  95. TTestMethod18 = function(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Extended): Extended of object;
  96. TTestMethod19 = function(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Comp): Comp of object;
  97. TTestMethod20 = function(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Currency): Currency of object;
  98. TTestMethod21 = procedure(var aArg1; out aArg2; const aArg3; {$ifdef fpc}constref{$else}const [ref]{$endif} aArg4) of object;
  99. TTestProc1 = procedure;
  100. TTestProc2 = function(aArg1: SizeInt): SizeInt;
  101. TTestProc3 = procedure(aArg1: AnsiString);
  102. TTestProc4 = procedure(aArg1: ShortString);
  103. TTestProc5 = function: AnsiString;
  104. TTestProc6 = function: ShortString;
  105. TTestProc7 = procedure(aArg1: SizeInt; var aArg2: SizeInt; out aArg3: SizeInt; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: SizeInt);
  106. TTestProc8 = procedure(aArg1: AnsiString; var aArg2: AnsiString; out aArg3: AnsiString; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: AnsiString);
  107. TTestProc9 = procedure(aArg1: ShortString; var aArg2: ShortString; out aArg3: ShortString; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: ShortString);
  108. TTestProc10 = procedure(aArg1: Single; var aArg2: Single; out aArg3: Single; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Single);
  109. TTestProc11 = procedure(aArg1: Double; var aArg2: Double; out aArg3: Double; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Double);
  110. TTestProc12 = procedure(aArg1: Extended; var aArg2: Extended; out aArg3: Extended; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Extended);
  111. TTestProc13 = procedure(aArg1: Comp; var aArg2: Comp; out aArg3: Comp; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Comp);
  112. TTestProc14 = procedure(aArg1: Currency; var aArg2: Currency; out aArg3: Currency; {$ifdef fpc}constref{$else}const [ref]{$endif}aArg4: Currency);
  113. TTestProc15 = function(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: SizeInt): SizeInt;
  114. TTestProc16 = function(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Single): Single;
  115. TTestProc17 = function(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Double): Double;
  116. TTestProc18 = function(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Extended): Extended;
  117. TTestProc19 = function(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Comp): Comp;
  118. TTestProc20 = function(aArg1, aArg2, aArg3, aArg4, aArg5, aArg6, aArg7, aArg8, aArg9, aArg10: Currency): Currency;
  119. TTestProc21 = procedure(var aArg1; out aArg2; const aArg3; {$ifdef fpc}constref{$else}const [ref]{$endif} aArg4);
  120. const
  121. SingleArg1: Single = 1.23;
  122. SingleArg2In: Single = 3.21;
  123. SingleArg2Out: Single = 2.34;
  124. SingleArg3Out: Single = 9.87;
  125. SingleArg4: Single = 7.89;
  126. SingleRes: Single = 4.32;
  127. SingleAddArg1 = Single(1.23);
  128. SingleAddArg2 = Single(2.34);
  129. SingleAddArg3 = Single(3.45);
  130. SingleAddArg4 = Single(4.56);
  131. SingleAddArg5 = Single(5.67);
  132. SingleAddArg6 = Single(9.87);
  133. SingleAddArg7 = Single(8.76);
  134. SingleAddArg8 = Single(7.65);
  135. SingleAddArg9 = Single(6.54);
  136. SingleAddArg10 = Single(5.43);
  137. SingleAddRes = SingleAddArg1 + SingleAddArg2 + SingleAddArg3 + SingleAddArg4 + SingleAddArg5 +
  138. SingleAddArg6 + SingleAddArg7 + SingleAddArg8 + SingleAddArg9 + SingleAddArg10;
  139. DoubleArg1: Double = 1.23;
  140. DoubleArg2In: Double = 3.21;
  141. DoubleArg2Out: Double = 2.34;
  142. DoubleArg3Out: Double = 9.87;
  143. DoubleArg4: Double = 7.89;
  144. DoubleRes: Double = 4.32;
  145. DoubleAddArg1 = Double(1.23);
  146. DoubleAddArg2 = Double(2.34);
  147. DoubleAddArg3 = Double(3.45);
  148. DoubleAddArg4 = Double(4.56);
  149. DoubleAddArg5 = Double(5.67);
  150. DoubleAddArg6 = Double(9.87);
  151. DoubleAddArg7 = Double(8.76);
  152. DoubleAddArg8 = Double(7.65);
  153. DoubleAddArg9 = Double(6.54);
  154. DoubleAddArg10 = Double(5.43);
  155. DoubleAddRes = DoubleAddArg1 + DoubleAddArg2 + DoubleAddArg3 + DoubleAddArg4 + DoubleAddArg5 +
  156. DoubleAddArg6 + DoubleAddArg7 + DoubleAddArg8 + DoubleAddArg9 + DoubleAddArg10;
  157. ExtendedArg1: Extended = 1.23;
  158. ExtendedArg2In: Extended = 3.21;
  159. ExtendedArg2Out: Extended = 2.34;
  160. ExtendedArg3Out: Extended = 9.87;
  161. ExtendedArg4: Extended = 7.89;
  162. ExtendedRes: Extended = 4.32;
  163. ExtendedAddArg1 = Extended(1.23);
  164. ExtendedAddArg2 = Extended(2.34);
  165. ExtendedAddArg3 = Extended(3.45);
  166. ExtendedAddArg4 = Extended(4.56);
  167. ExtendedAddArg5 = Extended(5.67);
  168. ExtendedAddArg6 = Extended(9.87);
  169. ExtendedAddArg7 = Extended(8.76);
  170. ExtendedAddArg8 = Extended(7.65);
  171. ExtendedAddArg9 = Extended(6.54);
  172. ExtendedAddArg10 = Extended(5.43);
  173. ExtendedAddRes = ExtendedAddArg1 + ExtendedAddArg2 + ExtendedAddArg3 + ExtendedAddArg4 + ExtendedAddArg5 +
  174. ExtendedAddArg6 + ExtendedAddArg7 + ExtendedAddArg8 + ExtendedAddArg9 + ExtendedAddArg10;
  175. CurrencyArg1: Currency = 1.23;
  176. CurrencyArg2In: Currency = 3.21;
  177. CurrencyArg2Out: Currency = 2.34;
  178. CurrencyArg3Out: Currency = 9.87;
  179. CurrencyArg4: Currency = 7.89;
  180. CurrencyRes: Currency = 4.32;
  181. CurrencyAddArg1 = Currency(1.23);
  182. CurrencyAddArg2 = Currency(2.34);
  183. CurrencyAddArg3 = Currency(3.45);
  184. CurrencyAddArg4 = Currency(4.56);
  185. CurrencyAddArg5 = Currency(5.67);
  186. CurrencyAddArg6 = Currency(9.87);
  187. CurrencyAddArg7 = Currency(8.76);
  188. CurrencyAddArg8 = Currency(7.65);
  189. CurrencyAddArg9 = Currency(6.54);
  190. CurrencyAddArg10 = Currency(5.43);
  191. CurrencyAddRes = CurrencyAddArg1 + CurrencyAddArg2 + CurrencyAddArg3 + CurrencyAddArg4 + CurrencyAddArg5 +
  192. CurrencyAddArg6 + CurrencyAddArg7 + CurrencyAddArg8 + CurrencyAddArg9 + CurrencyAddArg10;
  193. CompArg1: Comp = 123;
  194. CompArg2In: Comp = 321;
  195. CompArg2Out: Comp = 234;
  196. CompArg3Out: Comp = 987;
  197. CompArg4: Comp = 789;
  198. CompRes: Comp = 432;
  199. CompAddArg1 = Comp(123);
  200. CompAddArg2 = Comp(234);
  201. CompAddArg3 = Comp(345);
  202. CompAddArg4 = Comp(456);
  203. CompAddArg5 = Comp(567);
  204. CompAddArg6 = Comp(987);
  205. CompAddArg7 = Comp(876);
  206. CompAddArg8 = Comp(765);
  207. CompAddArg9 = Comp(654);
  208. CompAddArg10 = Comp(543);
  209. CompAddRes = CompAddArg1 + CompAddArg2 + CompAddArg3 + CompAddArg4 + CompAddArg5 +
  210. CompAddArg6 + CompAddArg7 + CompAddArg8 + CompAddArg9 + CompAddArg10;
  211. { TTestImpl }
  212. {$ifdef fpc}
  213. procedure TTestImpl.Status(const aMsg: String);
  214. begin
  215. {$ifdef debug}
  216. Writeln(aMsg);
  217. {$endif}
  218. end;
  219. procedure TTestImpl.Status(const aMsg: String; const aArgs: array of const);
  220. begin
  221. {$ifdef debug}
  222. Writeln(Format(aMsg, aArgs));
  223. {$endif}
  224. end;
  225. {$endif}
  226. procedure TTestImpl.OnHandleIntfMethod(aMethod: TRttiMethod; const aArgs: TValueArray; out aResult: TValue);
  227. var
  228. selfofs, i: SizeInt;
  229. name: String;
  230. begin
  231. selfofs := 1;
  232. Status('In Callback');
  233. InvokedMethodName := aMethod.Name;
  234. Status('Self: ' + HexStr(Self));
  235. if Assigned(aMethod.ReturnType) then
  236. aResult := CopyValue(ResultValue);
  237. Status('Setting input args');
  238. SetLength(InputArgs, Length(aArgs));
  239. for i := 0 to High(aArgs) do begin
  240. Status('Arg %d: %p %p', [i, aArgs[i].GetReferenceToRawData, PPointer(aArgs[i].GetReferenceToRawData)^]);
  241. if Assigned(InputUntypedTypes[i]) then
  242. TValue.Make(PPointer(aArgs[i].GetReferenceToRawData)^, InputUntypedTypes[i], InputArgs[i])
  243. else
  244. InputArgs[i] := CopyValue(aArgs[i]);
  245. end;
  246. Status('Setting output args');
  247. { Note: account for Self }
  248. for i := 0 to High(InOutMapping) do begin
  249. Status('OutputArg %d -> Arg %d', [i, InOutMapping[i] + selfofs]);
  250. { check input arg type? }
  251. Move(OutputArgs[i].GetReferenceToRawData^, aArgs[InOutMapping[i] + selfofs].GetReferenceToRawData^, OutputArgs[i].DataSize);
  252. end;
  253. Status('Callback done');
  254. end;
  255. procedure TTestImpl.DoIntfImpl(aIntf: IInterface; aTypeInfo: PTypeInfo; aIndex: LongInt; aInputArgs, aOutputArgs: TValueArray; aInOutMapping: array of SizeInt; aResult: TValue);
  256. var
  257. context: TRttiContext;
  258. t: TRttiType;
  259. instance, res: TValue;
  260. method: TRttiMethod;
  261. i: SizeInt;
  262. input: array of TValue;
  263. intf: TRttiInterfaceType;
  264. mrec: TMethod;
  265. name: String;
  266. params: array of TRttiParameter;
  267. begin
  268. name := 'TestMethod' + IntToStr(aIndex);
  269. context := TRttiContext.Create;
  270. try
  271. t := context.GetType(aTypeInfo);
  272. Check(t is TRttiInterfaceType, 'Not a interface type: ' + aTypeInfo^.Name);
  273. intf := t as TRttiInterfaceType;
  274. method := intf.GetMethod(name);
  275. Check(Assigned(method), 'Method not found: ' + name);
  276. Status('Executing method %s', [name]);
  277. CheckEquals(Length(aOutputArgs), Length(aInOutMapping), 'Invalid in/out mapping');
  278. Check(Length(aOutputArgs) <= Length(aInputArgs), 'Output args not part of input args');
  279. params := method.GetParameters;
  280. TValue.Make(@aIntf, aTypeInfo, instance);
  281. { arguments might be modified by Invoke (Note: Copy() does not uniquify the
  282. IValueData of managed types) }
  283. SetLength(input, Length(aInputArgs) + 1);
  284. SetLength(InputUntypedTypes, Length(aInputArgs) + 1);
  285. input[0] := instance;
  286. InputUntypedTypes[0] := Nil;
  287. for i := 0 to High(aInputArgs) do begin
  288. input[i + 1] := CopyValue(aInputArgs[i]);
  289. if not Assigned(params[i].ParamType) then
  290. InputUntypedTypes[i + 1] := aInputArgs[i].TypeInfo
  291. else
  292. InputUntypedTypes[i + 1] := Nil;
  293. end;
  294. SetLength(InOutMapping, Length(aInOutMapping));
  295. for i := 0 to High(InOutMapping) do
  296. InOutMapping[i] := aInOutMapping[i];
  297. SetLength(OutputArgs, Length(aOutputArgs));
  298. for i := 0 to High(OutputArgs) do
  299. OutputArgs[i] := CopyValue(aOutputArgs[i]);
  300. ResultValue := aResult;
  301. res := method.Invoke(instance, aInputArgs);
  302. Status('After invoke');
  303. CheckEquals(name, InvokedMethodName, 'Invoked method name differs for ' + name);
  304. Check(EqualValues(ResultValue, res), 'Reported result value differs from returned for ' + name);
  305. Check(EqualValues(aResult, res), 'Expected result value differs from returned for ' + name);
  306. CheckEquals(Length(input), Length(InputArgs), 'Count of input args differs for ' + name);
  307. for i := 0 to High(input) do begin
  308. Check(EqualValues(input[i], InputArgs[i]), Format('Input argument %d differs for %s', [i + 1, name]));
  309. end;
  310. for i := 0 to High(aOutputArgs) do begin
  311. Check(EqualValues(aOutputArgs[i], aInputArgs[InOutMapping[i]]), Format('New output argument %d differs from expected output for %s', [i + 1, name]));
  312. end;
  313. finally
  314. context.Free;
  315. end;
  316. end;
  317. {$ifdef fpc}
  318. procedure TTestImpl.OnHandleInvokable(aInvokable: TRttiInvokableType; const aArgs: TValueArray; out
  319. aResult: TValue);
  320. var
  321. selfofs, i: SizeInt;
  322. begin
  323. CheckTrue((aInvokable is TRttiMethodType) or (aInvokable is TRttiProcedureType), 'Invokable is not a method or procedure variable: ' + aInvokable.ClassName);
  324. selfofs := 0;
  325. if aInvokable is TRttiMethodType then
  326. selfofs := 1;
  327. Status('In Callback');
  328. Status('Self: ' + HexStr(Self));
  329. if Assigned(aInvokable.ReturnType) then
  330. aResult := CopyValue(ResultValue);
  331. Status('Setting input args');
  332. SetLength(InputArgs, Length(aArgs));
  333. for i := 0 to High(aArgs) do begin
  334. Status('Arg %d: %p %p', [i, aArgs[i].GetReferenceToRawData, PPointer(aArgs[i].GetReferenceToRawData)^]);
  335. if Assigned(InputUntypedTypes[i]) then
  336. TValue.Make(PPointer(aArgs[i].GetReferenceToRawData)^, InputUntypedTypes[i], InputArgs[i])
  337. else
  338. InputArgs[i] := CopyValue(aArgs[i]);
  339. end;
  340. Status('Setting output args');
  341. { Note: account for Self }
  342. for i := 0 to High(InOutMapping) do begin
  343. Status('OutputArg %d -> Arg %d', [i, InOutMapping[i] + selfofs]);
  344. { check input arg type? }
  345. Move(OutputArgs[i].GetReferenceToRawData^, aArgs[InOutMapping[i] + selfofs].GetReferenceToRawData^, OutputArgs[i].DataSize);
  346. end;
  347. Status('Callback done');
  348. end;
  349. procedure TTestImpl.DoMethodImpl(aTypeInfo: PTypeInfo; aInputArgs,
  350. aOutputArgs: TValueArray; aInOutMapping: array of SizeInt; aResult: TValue);
  351. var
  352. context: TRttiContext;
  353. t: TRttiType;
  354. callable, res: TValue;
  355. method: TRttiMethodType;
  356. i: SizeInt;
  357. input: array of TValue;
  358. impl: TMethodImplementation;
  359. mrec: TMethod;
  360. name: String;
  361. params: array of TRttiParameter;
  362. begin
  363. name := aTypeInfo^.Name;
  364. impl := Nil;
  365. context := TRttiContext.Create;
  366. try
  367. t := context.GetType(aTypeInfo);
  368. Check(t is TRttiMethodType, 'Not a method variable: ' + name);
  369. method := t as TRttiMethodType;
  370. Status('Executing method %s', [name]);
  371. CheckEquals(Length(aOutputArgs), Length(aInOutMapping), 'Invalid in/out mapping');
  372. Check(Length(aOutputArgs) <= Length(aInputArgs), 'Output args not part of input args');
  373. params := method.GetParameters;
  374. { arguments might be modified by Invoke (Note: Copy() does not uniquify the
  375. IValueData of managed types) }
  376. SetLength(input, Length(aInputArgs) + 1);
  377. SetLength(InputUntypedTypes, Length(aInputArgs) + 1);
  378. input[0] := GetPointerValue(Self);
  379. InputUntypedTypes[0] := Nil;
  380. for i := 0 to High(aInputArgs) do begin
  381. input[i + 1] := CopyValue(aInputArgs[i]);
  382. if not Assigned(params[i].ParamType) then
  383. InputUntypedTypes[i + 1] := aInputArgs[i].TypeInfo
  384. else
  385. InputUntypedTypes[i + 1] := Nil;
  386. end;
  387. try
  388. impl := method.CreateImplementation({$ifdef fpc}@{$endif}OnHandleInvokable);
  389. except
  390. on e: ENotImplemented do
  391. Exit;
  392. end;
  393. CheckNotNull(impl, 'Method implementation is Nil');
  394. mrec.Data := Self;
  395. mrec.Code := impl.CodeAddress;
  396. TValue.Make(@mrec, aTypeInfo, callable);
  397. SetLength(InOutMapping, Length(aInOutMapping));
  398. for i := 0 to High(InOutMapping) do
  399. InOutMapping[i] := aInOutMapping[i];
  400. SetLength(OutputArgs, Length(aOutputArgs));
  401. for i := 0 to High(OutputArgs) do
  402. OutputArgs[i] := CopyValue(aOutputArgs[i]);
  403. ResultValue := aResult;
  404. res := method.Invoke(callable, aInputArgs);
  405. Status('After invoke');
  406. Check(EqualValues(ResultValue, res), 'Reported result value differs from returned for ' + name);
  407. Check(EqualValues(aResult, res), 'Expected result value differs from returned for ' + name);
  408. CheckEquals(Length(input), Length(InputArgs), 'Count of input args differs for ' + name);
  409. for i := 0 to High(input) do begin
  410. Check(EqualValues(input[i], InputArgs[i]), Format('Input argument %d differs for %s', [i + 1, name]));
  411. end;
  412. for i := 0 to High(aOutputArgs) do begin
  413. Check(EqualValues(aOutputArgs[i], aInputArgs[InOutMapping[i]]), Format('New output argument %d differs from expected output for %s', [i + 1, name]));
  414. end;
  415. finally
  416. impl.Free;
  417. context.Free;
  418. end;
  419. end;
  420. procedure TTestImpl.DoProcImpl(aTypeInfo: PTypeInfo; aInputArgs,
  421. aOutputArgs: TValueArray; aInOutMapping: array of SizeInt; aResult: TValue);
  422. var
  423. context: TRttiContext;
  424. t: TRttiType;
  425. callable, res: TValue;
  426. proc: TRttiProcedureType;
  427. i: SizeInt;
  428. input: array of TValue;
  429. impl: TMethodImplementation;
  430. name: String;
  431. cp: CodePointer;
  432. params: array of TRttiParameter;
  433. begin
  434. name := aTypeInfo^.Name;
  435. impl := Nil;
  436. context := TRttiContext.Create;
  437. try
  438. t := context.GetType(aTypeInfo);
  439. Check(t is TRttiProcedureType, 'Not a procedure variable: ' + name);
  440. proc := t as TRttiProcedureType;
  441. Status('Executing procedure %s', [name]);
  442. CheckEquals(Length(aOutputArgs), Length(aInOutMapping), 'Invalid in/out mapping');
  443. Check(Length(aOutputArgs) <= Length(aInputArgs), 'Output args not part of input args');
  444. params := proc.GetParameters;
  445. { arguments might be modified by Invoke (Note: Copy() does not uniquify the
  446. IValueData of managed types) }
  447. SetLength(input, Length(aInputArgs));
  448. SetLength(InputUntypedTypes, Length(aInputArgs));
  449. for i := 0 to High(aInputArgs) do begin
  450. input[i] := CopyValue(aInputArgs[i]);
  451. if not Assigned(params[i].ParamType) then
  452. InputUntypedTypes[i] := aInputArgs[i].TypeInfo
  453. else
  454. InputUntypedTypes[i] := Nil;
  455. end;
  456. try
  457. impl := proc.CreateImplementation({$ifdef fpc}@{$endif}OnHandleInvokable);
  458. except
  459. on e: ENotImplemented do
  460. Exit;
  461. end;
  462. CheckNotNull(impl, 'Method implementation is Nil');
  463. cp := impl.CodeAddress;
  464. TValue.Make(@cp, aTypeInfo, callable);
  465. SetLength(InOutMapping, Length(aInOutMapping));
  466. for i := 0 to High(InOutMapping) do
  467. InOutMapping[i] := aInOutMapping[i];
  468. SetLength(OutputArgs, Length(aOutputArgs));
  469. for i := 0 to High(OutputArgs) do
  470. OutputArgs[i] := CopyValue(aOutputArgs[i]);
  471. ResultValue := aResult;
  472. res := proc.Invoke(callable, aInputArgs);
  473. Status('After invoke');
  474. Check(EqualValues(ResultValue, res), 'Reported result value differs from returned for ' + name);
  475. Check(EqualValues(aResult, res), 'Expected result value differs from returned for ' + name);
  476. CheckEquals(Length(input), Length(InputArgs), 'Count of input args differs for ' + name);
  477. for i := 0 to High(input) do begin
  478. Check(EqualValues(input[i], InputArgs[i]), Format('Input argument %d differs for %s', [i + 1, name]));
  479. end;
  480. for i := 0 to High(aOutputArgs) do begin
  481. Check(EqualValues(aOutputArgs[i], aInputArgs[InOutMapping[i]]), Format('New output argument %d differs from expected output for %s', [i + 1, name]));
  482. end;
  483. finally
  484. impl.Free;
  485. context.Free;
  486. end;
  487. end;
  488. {$endif}
  489. {$ifndef InLazIDE}
  490. {$ifdef fpc}generic{$endif} procedure TTestImpl.GenDoIntfImpl<T>(aIntf: T; aIndex: LongInt; aInputArgs, aOutputArgs: TValueArray; aInOutMapping: array of SizeInt; aResult: TValue);
  491. begin
  492. DoIntfImpl(aIntf, TypeInfo(T), aIndex, aInputArgs, aOutputArgs, aInOutMapping, aResult);
  493. end;
  494. {$ifdef fpc}generic{$endif} procedure TTestImpl.GenDoMethodImpl<T>(aInputArgs, aOutputArgs: TValueArray; aInOutMapping: array of SizeInt; aResult: TValue);
  495. begin
  496. DoMethodImpl(TypeInfo(T), aInputArgs, aOutputArgs, aInOutMapping, aResult);
  497. end;
  498. {$ifdef fpc}generic{$endif} procedure TTestImpl.GenDoProcImpl<T>(aInputArgs, aOutputArgs: TValueArray; aInOutMapping: array of SizeInt; aResult: TValue);
  499. begin
  500. DoProcImpl(TypeInfo(T), aInputArgs, aOutputArgs, aInOutMapping, aResult);
  501. end;
  502. {$endif}
  503. procedure TTestImpl.TestIntfMethods;
  504. var
  505. intf: ITestInterface;
  506. begin
  507. try
  508. intf := TVirtualInterface.Create(PTypeInfo(TypeInfo(ITestInterface)), {$ifdef fpc}@{$endif}OnHandleIntfMethod) as ITestInterface;
  509. except
  510. on e: ENotImplemented do
  511. Ignore('TVirtualInterface not supported for ' + {$I %FPCTARGETCPU%} + '-' + {$I %FPCTARGETOS%});
  512. end;
  513. Check(Assigned(intf), 'ITestInterface instance is Nil');
  514. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 1, [], [], [], TValue.Empty);
  515. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 2, [GetIntValue(42)], [], [], GetIntValue(21));
  516. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 3, [GetAnsiString('Hello World')], [], [], TValue.Empty);
  517. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 4, [GetShortString('Hello World')], [], [], TValue.Empty);
  518. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 5, [], [], [], GetAnsiString('Hello World'));
  519. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 6, [], [], [], GetShortString('Hello World'));
  520. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 7, [
  521. GetIntValue(1234), GetIntValue(4321), GetIntValue(0), GetIntValue(9876)
  522. ], [
  523. GetIntValue(5678), GetIntValue(6789)
  524. ], [1, 2], TValue.Empty);
  525. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 8, [
  526. GetAnsiString('Alpha'), GetAnsiString('Beta'), GetAnsiString(''), GetAnsiString('Delta')
  527. ], [
  528. GetAnsiString('Gamma'), GetAnsiString('Epsilon')
  529. ], [1, 2], TValue.Empty);
  530. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 9, [
  531. GetShortString('Alpha'), GetShortString('Beta'), GetShortString(''), GetShortString('Delta')
  532. ], [
  533. GetShortString('Gamma'), GetShortString('Epsilon')
  534. ], [1, 2], TValue.Empty);
  535. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 10, [
  536. GetSingleValue(SingleArg1), GetSingleValue(SingleArg2In), GetSingleValue(0), GetSingleValue(SingleArg4)
  537. ], [
  538. GetSingleValue(SingleArg2Out), GetSingleValue(SingleArg3Out)
  539. ], [1, 2], TValue.Empty);
  540. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 11, [
  541. GetDoubleValue(DoubleArg1), GetDoubleValue(DoubleArg2In), GetDoubleValue(0), GetDoubleValue(DoubleArg4)
  542. ], [
  543. GetDoubleValue(DoubleArg2Out), GetDoubleValue(DoubleArg3Out)
  544. ], [1, 2], TValue.Empty);
  545. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 12, [
  546. GetExtendedValue(ExtendedArg1), GetExtendedValue(ExtendedArg2In), GetExtendedValue(0), GetExtendedValue(ExtendedArg4)
  547. ], [
  548. GetExtendedValue(ExtendedArg2Out), GetExtendedValue(ExtendedArg3Out)
  549. ], [1, 2], TValue.Empty);
  550. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 13, [
  551. GetCompValue(CompArg1), GetCompValue(CompArg2In), GetCompValue(0), GetCompValue(CompArg4)
  552. ], [
  553. GetCompValue(CompArg2Out), GetCompValue(CompArg3Out)
  554. ], [1, 2], TValue.Empty);
  555. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 14, [
  556. GetCurrencyValue(CurrencyArg1), GetCurrencyValue(CurrencyArg2In), GetCurrencyValue(0), GetCurrencyValue(CurrencyArg4)
  557. ], [
  558. GetCurrencyValue(CurrencyArg2Out), GetCurrencyValue(CurrencyArg3Out)
  559. ], [1, 2], TValue.Empty);
  560. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 15, [
  561. GetIntValue(1), GetIntValue(2), GetIntValue(3), GetIntValue(4), GetIntValue(5),
  562. GetIntValue(6), GetIntValue(7), GetIntValue(8), GetIntValue(9), GetIntValue(10)
  563. ], [], [], GetIntValue(11));
  564. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 16, [
  565. GetSingleValue(SingleAddArg1), GetSingleValue(SingleAddArg2), GetSingleValue(SingleAddArg3), GetSingleValue(SingleAddArg4), GetSingleValue(SingleAddArg5),
  566. GetSingleValue(SingleAddArg6), GetSingleValue(SingleAddArg7), GetSingleValue(SingleAddArg8), GetSingleValue(SingleAddArg9), GetSingleValue(SingleAddArg10)
  567. ], [], [], GetSingleValue(SingleAddRes));
  568. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 17, [
  569. GetDoubleValue(DoubleAddArg1), GetDoubleValue(DoubleAddArg2), GetDoubleValue(DoubleAddArg3), GetDoubleValue(DoubleAddArg4), GetDoubleValue(DoubleAddArg5),
  570. GetDoubleValue(DoubleAddArg6), GetDoubleValue(DoubleAddArg7), GetDoubleValue(DoubleAddArg8), GetDoubleValue(DoubleAddArg9), GetDoubleValue(DoubleAddArg10)
  571. ], [], [], GetDoubleValue(DoubleAddRes));
  572. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 18, [
  573. GetExtendedValue(ExtendedAddArg1), GetExtendedValue(ExtendedAddArg2), GetExtendedValue(ExtendedAddArg3), GetExtendedValue(ExtendedAddArg4), GetExtendedValue(ExtendedAddArg5),
  574. GetExtendedValue(ExtendedAddArg6), GetExtendedValue(ExtendedAddArg7), GetExtendedValue(ExtendedAddArg8), GetExtendedValue(ExtendedAddArg9), GetExtendedValue(ExtendedAddArg10)
  575. ], [], [], GetExtendedValue(ExtendedAddRes));
  576. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 19, [
  577. GetCompValue(CompAddArg1), GetCompValue(CompAddArg2), GetCompValue(CompAddArg3), GetCompValue(CompAddArg4), GetCompValue(CompAddArg5),
  578. GetCompValue(CompAddArg6), GetCompValue(CompAddArg7), GetCompValue(CompAddArg8), GetCompValue(CompAddArg9), GetCompValue(CompAddArg10)
  579. ], [], [], GetCompValue(CompAddRes));
  580. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 20, [
  581. GetCurrencyValue(CurrencyAddArg1), GetCurrencyValue(CurrencyAddArg2), GetCurrencyValue(CurrencyAddArg3), GetCurrencyValue(CurrencyAddArg4), GetCurrencyValue(CurrencyAddArg5),
  582. GetCurrencyValue(CurrencyAddArg6), GetCurrencyValue(CurrencyAddArg7), GetCurrencyValue(CurrencyAddArg8), GetCurrencyValue(CurrencyAddArg9), GetCurrencyValue(CurrencyAddArg10)
  583. ], [], [], GetCurrencyValue(CurrencyAddRes));
  584. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 21, [
  585. GetIntValue(1234), GetIntValue(4321), GetIntValue(0), GetIntValue(9876)
  586. ], [
  587. GetIntValue(5678), GetIntValue(6789)
  588. ], [0, 1], TValue.Empty);
  589. {$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 21, [
  590. GetAnsiString('Alpha'), GetAnsiString('Beta'), GetAnsiString(''), GetAnsiString('Delta')
  591. ], [
  592. GetAnsiString('Gamma'), GetAnsiString('Epsilon')
  593. ], [0, 1], TValue.Empty);
  594. { for some reason this fails, though it fails in Delphi as well :/ }
  595. {{$ifdef fpc}specialize{$endif}GenDoIntfImpl<ITestInterface>(intf, 21, [
  596. GetShortString('Alpha'), GetShortString('Beta'), GetShortString(''), GetShortString('Delta')
  597. ], [
  598. GetShortString('Gamma'), GetShortString('Epsilon')
  599. ], [0, 1], TValue.Empty);}
  600. end;
  601. {$ifdef fpc}
  602. procedure TTestImpl.TestMethodVars;
  603. begin
  604. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod1>([], [], [], TValue.Empty);
  605. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod2>([GetIntValue(42)], [], [], GetIntValue(21));
  606. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod3>([GetAnsiString('Hello World')], [], [], TValue.Empty);
  607. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod4>([GetShortString('Hello World')], [], [], TValue.Empty);
  608. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod5>([], [], [], GetAnsiString('Hello World'));
  609. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod6>([], [], [], GetShortString('Hello World'));
  610. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod7>([
  611. GetIntValue(1234), GetIntValue(4321), GetIntValue(0), GetIntValue(9876)
  612. ], [
  613. GetIntValue(5678), GetIntValue(6789)
  614. ], [1, 2], TValue.Empty);
  615. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod8>([
  616. GetAnsiString('Alpha'), GetAnsiString('Beta'), GetAnsiString(''), GetAnsiString('Delta')
  617. ], [
  618. GetAnsiString('Gamma'), GetAnsiString('Epsilon')
  619. ], [1, 2], TValue.Empty);
  620. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod9>([
  621. GetShortString('Alpha'), GetShortString('Beta'), GetShortString(''), GetShortString('Delta')
  622. ], [
  623. GetShortString('Gamma'), GetShortString('Epsilon')
  624. ], [1, 2], TValue.Empty);
  625. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod10>([
  626. GetSingleValue(SingleArg1), GetSingleValue(SingleArg2In), GetSingleValue(0), GetSingleValue(SingleArg4)
  627. ], [
  628. GetSingleValue(SingleArg2Out), GetSingleValue(SingleArg3Out)
  629. ], [1, 2], TValue.Empty);
  630. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod11>([
  631. GetDoubleValue(DoubleArg1), GetDoubleValue(DoubleArg2In), GetDoubleValue(0), GetDoubleValue(DoubleArg4)
  632. ], [
  633. GetDoubleValue(DoubleArg2Out), GetDoubleValue(DoubleArg3Out)
  634. ], [1, 2], TValue.Empty);
  635. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod12>([
  636. GetExtendedValue(ExtendedArg1), GetExtendedValue(ExtendedArg2In), GetExtendedValue(0), GetExtendedValue(ExtendedArg4)
  637. ], [
  638. GetExtendedValue(ExtendedArg2Out), GetExtendedValue(ExtendedArg3Out)
  639. ], [1, 2], TValue.Empty);
  640. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod13>([
  641. GetCompValue(CompArg1), GetCompValue(CompArg2In), GetCompValue(0), GetCompValue(CompArg4)
  642. ], [
  643. GetCompValue(CompArg2Out), GetCompValue(CompArg3Out)
  644. ], [1, 2], TValue.Empty);
  645. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod14>([
  646. GetCurrencyValue(CurrencyArg1), GetCurrencyValue(CurrencyArg2In), GetCurrencyValue(0), GetCurrencyValue(CurrencyArg4)
  647. ], [
  648. GetCurrencyValue(CurrencyArg2Out), GetCurrencyValue(CurrencyArg3Out)
  649. ], [1, 2], TValue.Empty);
  650. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod15>([
  651. GetIntValue(1), GetIntValue(2), GetIntValue(3), GetIntValue(4), GetIntValue(5),
  652. GetIntValue(6), GetIntValue(7), GetIntValue(8), GetIntValue(9), GetIntValue(10)
  653. ], [], [], GetIntValue(11));
  654. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod16>([
  655. GetSingleValue(SingleAddArg1), GetSingleValue(SingleAddArg2), GetSingleValue(SingleAddArg3), GetSingleValue(SingleAddArg4), GetSingleValue(SingleAddArg5),
  656. GetSingleValue(SingleAddArg6), GetSingleValue(SingleAddArg7), GetSingleValue(SingleAddArg8), GetSingleValue(SingleAddArg9), GetSingleValue(SingleAddArg10)
  657. ], [], [], GetSingleValue(SingleAddRes));
  658. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod17>([
  659. GetDoubleValue(DoubleAddArg1), GetDoubleValue(DoubleAddArg2), GetDoubleValue(DoubleAddArg3), GetDoubleValue(DoubleAddArg4), GetDoubleValue(DoubleAddArg5),
  660. GetDoubleValue(DoubleAddArg6), GetDoubleValue(DoubleAddArg7), GetDoubleValue(DoubleAddArg8), GetDoubleValue(DoubleAddArg9), GetDoubleValue(DoubleAddArg10)
  661. ], [], [], GetDoubleValue(DoubleAddRes));
  662. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod18>([
  663. GetExtendedValue(ExtendedAddArg1), GetExtendedValue(ExtendedAddArg2), GetExtendedValue(ExtendedAddArg3), GetExtendedValue(ExtendedAddArg4), GetExtendedValue(ExtendedAddArg5),
  664. GetExtendedValue(ExtendedAddArg6), GetExtendedValue(ExtendedAddArg7), GetExtendedValue(ExtendedAddArg8), GetExtendedValue(ExtendedAddArg9), GetExtendedValue(ExtendedAddArg10)
  665. ], [], [], GetExtendedValue(ExtendedAddRes));
  666. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod19>([
  667. GetCompValue(CompAddArg1), GetCompValue(CompAddArg2), GetCompValue(CompAddArg3), GetCompValue(CompAddArg4), GetCompValue(CompAddArg5),
  668. GetCompValue(CompAddArg6), GetCompValue(CompAddArg7), GetCompValue(CompAddArg8), GetCompValue(CompAddArg9), GetCompValue(CompAddArg10)
  669. ], [], [], GetCompValue(CompAddRes));
  670. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod20>([
  671. GetCurrencyValue(CurrencyAddArg1), GetCurrencyValue(CurrencyAddArg2), GetCurrencyValue(CurrencyAddArg3), GetCurrencyValue(CurrencyAddArg4), GetCurrencyValue(CurrencyAddArg5),
  672. GetCurrencyValue(CurrencyAddArg6), GetCurrencyValue(CurrencyAddArg7), GetCurrencyValue(CurrencyAddArg8), GetCurrencyValue(CurrencyAddArg9), GetCurrencyValue(CurrencyAddArg10)
  673. ], [], [], GetCurrencyValue(CurrencyAddRes));
  674. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod21>([
  675. GetIntValue(1234), GetIntValue(4321), GetIntValue(0), GetIntValue(9876)
  676. ], [
  677. GetIntValue(5678), GetIntValue(6789)
  678. ], [0, 1], TValue.Empty);
  679. {$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod21>([
  680. GetAnsiString('Alpha'), GetAnsiString('Beta'), GetAnsiString(''), GetAnsiString('Delta')
  681. ], [
  682. GetAnsiString('Gamma'), GetAnsiString('Epsilon')
  683. ], [0, 1], TValue.Empty);
  684. { for some reason this fails, though it fails in Delphi as well :/ }
  685. {{$ifdef fpc}specialize{$endif}GenDoMethodImpl<TTestMethod21>([
  686. GetShortString('Alpha'), GetShortString('Beta'), GetShortString(''), GetShortString('Delta')
  687. ], [
  688. GetShortString('Gamma'), GetShortString('Epsilon')
  689. ], [0, 1], TValue.Empty);}
  690. end;
  691. procedure TTestImpl.TestProcVars;
  692. begin
  693. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc1>([], [], [], TValue.Empty);
  694. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc2>([GetIntValue(42)], [], [], GetIntValue(21));
  695. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc3>([GetAnsiString('Hello World')], [], [], TValue.Empty);
  696. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc4>([GetShortString('Hello World')], [], [], TValue.Empty);
  697. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc5>([], [], [], GetAnsiString('Hello World'));
  698. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc6>([], [], [], GetShortString('Hello World'));
  699. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc7>([
  700. GetIntValue(1234), GetIntValue(4321), GetIntValue(0), GetIntValue(9876)
  701. ], [
  702. GetIntValue(5678), GetIntValue(6789)
  703. ], [1, 2], TValue.Empty);
  704. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc8>([
  705. GetAnsiString('Alpha'), GetAnsiString('Beta'), GetAnsiString(''), GetAnsiString('Delta')
  706. ], [
  707. GetAnsiString('Gamma'), GetAnsiString('Epsilon')
  708. ], [1, 2], TValue.Empty);
  709. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc9>([
  710. GetShortString('Alpha'), GetShortString('Beta'), GetShortString(''), GetShortString('Delta')
  711. ], [
  712. GetShortString('Gamma'), GetShortString('Epsilon')
  713. ], [1, 2], TValue.Empty);
  714. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc10>([
  715. GetSingleValue(SingleArg1), GetSingleValue(SingleArg2In), GetSingleValue(0), GetSingleValue(SingleArg4)
  716. ], [
  717. GetSingleValue(SingleArg2Out), GetSingleValue(SingleArg3Out)
  718. ], [1, 2], TValue.Empty);
  719. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc11>([
  720. GetDoubleValue(DoubleArg1), GetDoubleValue(DoubleArg2In), GetDoubleValue(0), GetDoubleValue(DoubleArg4)
  721. ], [
  722. GetDoubleValue(DoubleArg2Out), GetDoubleValue(DoubleArg3Out)
  723. ], [1, 2], TValue.Empty);
  724. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc12>([
  725. GetExtendedValue(ExtendedArg1), GetExtendedValue(ExtendedArg2In), GetExtendedValue(0), GetExtendedValue(ExtendedArg4)
  726. ], [
  727. GetExtendedValue(ExtendedArg2Out), GetExtendedValue(ExtendedArg3Out)
  728. ], [1, 2], TValue.Empty);
  729. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc13>([
  730. GetCompValue(CompArg1), GetCompValue(CompArg2In), GetCompValue(0), GetCompValue(CompArg4)
  731. ], [
  732. GetCompValue(CompArg2Out), GetCompValue(CompArg3Out)
  733. ], [1, 2], TValue.Empty);
  734. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc14>([
  735. GetCurrencyValue(CurrencyArg1), GetCurrencyValue(CurrencyArg2In), GetCurrencyValue(0), GetCurrencyValue(CurrencyArg4)
  736. ], [
  737. GetCurrencyValue(CurrencyArg2Out), GetCurrencyValue(CurrencyArg3Out)
  738. ], [1, 2], TValue.Empty);
  739. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc15>([
  740. GetIntValue(1), GetIntValue(2), GetIntValue(3), GetIntValue(4), GetIntValue(5),
  741. GetIntValue(6), GetIntValue(7), GetIntValue(8), GetIntValue(9), GetIntValue(10)
  742. ], [], [], GetIntValue(11));
  743. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc16>([
  744. GetSingleValue(SingleAddArg1), GetSingleValue(SingleAddArg2), GetSingleValue(SingleAddArg3), GetSingleValue(SingleAddArg4), GetSingleValue(SingleAddArg5),
  745. GetSingleValue(SingleAddArg6), GetSingleValue(SingleAddArg7), GetSingleValue(SingleAddArg8), GetSingleValue(SingleAddArg9), GetSingleValue(SingleAddArg10)
  746. ], [], [], GetSingleValue(SingleAddRes));
  747. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc17>([
  748. GetDoubleValue(DoubleAddArg1), GetDoubleValue(DoubleAddArg2), GetDoubleValue(DoubleAddArg3), GetDoubleValue(DoubleAddArg4), GetDoubleValue(DoubleAddArg5),
  749. GetDoubleValue(DoubleAddArg6), GetDoubleValue(DoubleAddArg7), GetDoubleValue(DoubleAddArg8), GetDoubleValue(DoubleAddArg9), GetDoubleValue(DoubleAddArg10)
  750. ], [], [], GetDoubleValue(DoubleAddRes));
  751. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc18>([
  752. GetExtendedValue(ExtendedAddArg1), GetExtendedValue(ExtendedAddArg2), GetExtendedValue(ExtendedAddArg3), GetExtendedValue(ExtendedAddArg4), GetExtendedValue(ExtendedAddArg5),
  753. GetExtendedValue(ExtendedAddArg6), GetExtendedValue(ExtendedAddArg7), GetExtendedValue(ExtendedAddArg8), GetExtendedValue(ExtendedAddArg9), GetExtendedValue(ExtendedAddArg10)
  754. ], [], [], GetExtendedValue(ExtendedAddRes));
  755. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc19>([
  756. GetCompValue(CompAddArg1), GetCompValue(CompAddArg2), GetCompValue(CompAddArg3), GetCompValue(CompAddArg4), GetCompValue(CompAddArg5),
  757. GetCompValue(CompAddArg6), GetCompValue(CompAddArg7), GetCompValue(CompAddArg8), GetCompValue(CompAddArg9), GetCompValue(CompAddArg10)
  758. ], [], [], GetCompValue(CompAddRes));
  759. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc20>([
  760. GetCurrencyValue(CurrencyAddArg1), GetCurrencyValue(CurrencyAddArg2), GetCurrencyValue(CurrencyAddArg3), GetCurrencyValue(CurrencyAddArg4), GetCurrencyValue(CurrencyAddArg5),
  761. GetCurrencyValue(CurrencyAddArg6), GetCurrencyValue(CurrencyAddArg7), GetCurrencyValue(CurrencyAddArg8), GetCurrencyValue(CurrencyAddArg9), GetCurrencyValue(CurrencyAddArg10)
  762. ], [], [], GetCurrencyValue(CurrencyAddRes));
  763. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc21>([
  764. GetIntValue(1234), GetIntValue(4321), GetIntValue(0), GetIntValue(9876)
  765. ], [
  766. GetIntValue(5678), GetIntValue(6789)
  767. ], [0, 1], TValue.Empty);
  768. {$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc21>([
  769. GetAnsiString('Alpha'), GetAnsiString('Beta'), GetAnsiString(''), GetAnsiString('Delta')
  770. ], [
  771. GetAnsiString('Gamma'), GetAnsiString('Epsilon')
  772. ], [0, 1], TValue.Empty);
  773. { for some reason this fails, though it fails in Delphi as well :/ }
  774. {{$ifdef fpc}specialize{$endif}GenDoProcImpl<TTestProc21>([
  775. GetShortString('Alpha'), GetShortString('Beta'), GetShortString(''), GetShortString('Delta')
  776. ], [
  777. GetShortString('Gamma'), GetShortString('Epsilon')
  778. ], [0, 1], TValue.Empty);}
  779. end;
  780. {$endif}
  781. initialization
  782. {$ifdef fpc}
  783. RegisterTest(TTestImpl);
  784. {$else fpc}
  785. RegisterTest(TTestImpl.Suite);
  786. {$endif fpc}
  787. end.