tw12038.pp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. {$M+}
  2. program RTTI132;
  3. {$IFDEF FPC}
  4. {$mode objfpc}{$H+}
  5. {$packenum 1}
  6. {$ELSE}
  7. {$APPTYPE CONSOLE}
  8. {$ENDIF}
  9. uses
  10. SysUtils,
  11. TypInfo,
  12. Classes;
  13. type
  14. TMyObject = class;
  15. TBatch = Procedure (Var S:String) of Object; stdcall;
  16. TProcess = function (Var S:String; const A:integer):int64 of Object; stdcall;
  17. TArray = function (Var Array1:Array of String; const P:Pointer; Out Out1:int64):int64 of Object; stdcall;
  18. TOnFour = function (A: array of byte; const B: array of byte;
  19. var C: array of byte; out D: array of byte): TComponent of object; stdcall;
  20. TOnFive = procedure (Component1: TComponent;
  21. var Component2: TComponent;
  22. out Component3: TComponent;
  23. const Component4: TComponent) of object; stdcall;
  24. TOnSix = function (const A: string; var Two: integer;
  25. out Three: TMyObject; Four: PInteger; Five: array of Byte;
  26. Six: integer): string of object; stdcall;
  27. TMyObject=Class(TObject)
  28. private
  29. FFieldOne : Integer;
  30. FFieldTwo : String;
  31. FOnBatch :TBatch;
  32. FOnFour: TOnFour;
  33. FOnFive: TOnFive;
  34. FOnSix: TOnSix;
  35. FOnProcess : TProcess;
  36. FOnArray: TArray;
  37. Procedure ProcNo1(Var S:String); stdcall;
  38. Procedure ProcNo2(Var S:String); stdcall;
  39. public
  40. Function IF_Exist:Boolean;
  41. Property FP1:Integer read FFieldOne Write FFieldOne;
  42. published
  43. Property FP2:String read FFieldTwo Write FFieldTwo ;
  44. Property OnTraitement:TBatch read FOnBatch Write FOnBatch;
  45. Property OnProcess:TProcess read FOnProcess Write FOnProcess;
  46. Property OnArray:TArray read FOnArray Write FOnArray;
  47. function FourthPublished(A: array of byte; const B: array of byte;
  48. var C: array of byte; out D: array of byte): TComponent; stdcall;
  49. procedure FifthPublished(Component1: TComponent;
  50. var Component2: TComponent;
  51. out Component3: TComponent;
  52. const Component4: TComponent); stdcall;
  53. function SixthPublished(const A: string; var Two: integer;
  54. out Three: TMyObject; Four: PInteger;
  55. Five: array of Byte; Six: integer): string; stdcall;
  56. property OnFour: TOnFour read FOnFour write FOnFour;
  57. property OnFive: TOnFive read FOnFive write FOnFive;
  58. property OnSix: TOnSix read FOnSix write FOnSix;
  59. end;
  60. PShortString=^ShortString;
  61. // This record is the same in typinfo.pas compiler source file TTypeData record
  62. PParameter= ^Parameter;
  63. Parameter=Record
  64. Flags: TParamFlags;
  65. ParamName: ShortString;
  66. TypeName: ShortString;
  67. end;
  68. ParametersMethod1=Record
  69. AMat : Array[1..20] of Parameter;
  70. // for function
  71. ResultType: ShortString;
  72. end;
  73. Var OneObject : TMyObject;
  74. NumI, I: Integer;
  75. List_of_Prop: TPropList;
  76. List_of_Param : ParametersMethod1;
  77. Function TMyObject.IF_Exist:Boolean;
  78. Begin
  79. result:=True;
  80. end;
  81. Procedure TMyObject.ProcNo1(Var S:String); stdcall;
  82. Begin
  83. S:='The Batch execute the procedure TMyObject.ProcNo1';
  84. end;
  85. Procedure TMyObject.ProcNo2(Var S:String); stdcall;
  86. Begin
  87. S:='The Batch execute the procedure TMyObject.ProcNo2';
  88. end;
  89. function TMyObject.FourthPublished(A: array of byte; const B: array of byte;
  90. var C: array of byte; out D: array of byte): TComponent; stdcall;
  91. begin
  92. Result := nil;
  93. end;
  94. procedure TMyObject.FifthPublished(Component1: TComponent;
  95. var Component2: TComponent;
  96. out Component3: TComponent;
  97. const Component4: TComponent); stdcall;
  98. begin
  99. end;
  100. function TMyObject.SixthPublished(const A: string; var Two: integer;
  101. out Three: TMyObject; Four: PInteger;
  102. Five: array of Byte; Six: integer): string; stdcall;
  103. begin
  104. end;
  105. Function BuildMethodDefinition(Liste: ParametersMethod1;NumI :Integer):String;
  106. //Build the definition of method
  107. var
  108. Definition: String;
  109. i: integer;
  110. begin
  111. Result:='';
  112. Definition := '(';
  113. For i:= 1 to NumI do
  114. begin
  115. if pfVar in Liste.AMat[I].Flags
  116. then Definition := Definition+('var ');
  117. if pfconst in Liste.AMat[I].Flags
  118. then Definition := Definition+('const ');
  119. if pfArray in Liste.AMat[I].Flags
  120. then Definition := Definition+('array of ');
  121. if pfAddress in Liste.AMat[I].Flags
  122. then Definition := Definition+('adresse ?'); // If Self ?
  123. if pfReference in Liste.AMat[I].Flags
  124. then Definition := Definition+('reference ?'); // ??
  125. if pfout in Liste.AMat[I].Flags
  126. then Definition := Definition+('out ');
  127. Definition := Format('%s%s: %s', [Definition, Liste.AMat[I].ParamName, Liste.AMat[I].TypeName]);
  128. If I<NumI
  129. then Definition := Definition + '; '
  130. end;
  131. Definition := Definition + ')';
  132. if Liste.ResultType<>''
  133. then Definition := Format('%s: %s', [Definition, Liste.ResultType]);
  134. Definition := Definition+' of object;';
  135. Result:=Definition;
  136. end;
  137. procedure SetArrayParameter(ParameterCurrent: PParameter; NumI :Integer; TypeMethode:TMethodKind);
  138. var
  139. TypeParameter : PShortString;
  140. i: integer;
  141. begin
  142. i := 1;
  143. while i <= NumI do
  144. begin
  145. List_of_Param.AMat[I].Flags:=ParameterCurrent^.Flags;
  146. List_of_Param.AMat[I].ParamName:=ParameterCurrent^.ParamName;
  147. // type parameter
  148. TypeParameter := Pointer(Integer(@ParameterCurrent^.ParamName) +
  149. Length(ParameterCurrent^.ParamName)+1);
  150. List_of_Param.AMat[I].TypeName:=TypeParameter^;
  151. // Finding Next parameter using a pointer
  152. inc(i);
  153. // Address of current parameter
  154. ParameterCurrent := PParameter(Integer(ParameterCurrent) +
  155. // size of Tparamflags
  156. SizeOf(TParamFlags) +
  157. // length of ParamName string
  158. (Length(ParameterCurrent^.ParamName) + 1) +
  159. // length of TypeParameter string
  160. (Length(TypeParameter^)+1));
  161. end;
  162. // If it is the last parameter and if the method is a fonction
  163. // Next Working for the result type function
  164. if TypeMethode = mkFunction
  165. then List_of_Param.ResultType:=PShortString(ParameterCurrent)^
  166. else List_of_Param.ResultType:='';
  167. end;
  168. procedure DisplayDetails(Informations : TPropInfo; const expectedresult: ansistring);
  169. var
  170. PropTypeZ : String;
  171. DTypeData: PTypeData;
  172. Method : TMethod;
  173. Resultat : String;
  174. OrdinalValue,
  175. CurrentParamPosition,
  176. ParamNameLength,
  177. i, j : integer;
  178. ParamName,
  179. TypeName : string;
  180. TypeData : PTypeData;
  181. newTypeInfo : PTypeInfo;
  182. EnumerationName : PString;
  183. ProcessThisProperty : boolean;
  184. Fu_ResultType: String;
  185. Flags: TParamFlags;
  186. Flag:byte;
  187. Definition: String;
  188. begin
  189. // Finding property type
  190. With Informations do
  191. begin
  192. Writeln('Property Type : ',PropType^.Name);
  193. Write('Getter :');
  194. if not Assigned(GetProc)
  195. then Writeln('Nil')
  196. else Writeln(Format('%p', [GetProc]));
  197. Write('Setter :');
  198. if not Assigned(SetProc)
  199. then Writeln('Nil')
  200. else Writeln(Format('%p', [SetProc]));
  201. Write('StoredProc :');
  202. if not Assigned(StoredProc)
  203. then Writeln('Nil')
  204. else Writeln(Format('%p%', [StoredProc]));
  205. Writeln('Index :',Index);
  206. Writeln('Default :',Default);
  207. Writeln('NameIndex :',NameIndex);
  208. case PropType^.Kind of
  209. tkInteger : writeln('<tkinteger>');
  210. tkLString : writeln('<tklstring>');
  211. //tkString : writeln('Longueur max ='); string pascal max 255?
  212. tkMethod :
  213. Begin
  214. writeln('>>> Methode Type >>>');
  215. //Information for the method type : tkmethod
  216. // TPropInfo.PropType= PPTypeInfo;
  217. // GetTypeData(TypeInfo: PTypeInfo) send PTypeData
  218. // PTypeData is for finding MethodKind
  219. {$IFDEF FPC}
  220. DTypeData:= GetTypeData(PTypeInfo(PropType));
  221. {$ELSE}
  222. DTypeData:= GetTypeData(PTypeInfo(PropType^));
  223. {$ENDIF}
  224. // Détermine le type de la méthode
  225. Case DTypeData^.MethodKind of
  226. mkProcedure: PropTypeZ := 'procedure';
  227. mkFunction: PropTypeZ := 'function';
  228. mkConstructor: PropTypeZ := 'constructor';
  229. mkDestructor: PropTypeZ := 'destructor';
  230. mkClassProcedure: PropTypeZ := 'class procedure';
  231. mkClassFunction: PropTypeZ := 'class function';
  232. end;
  233. Writeln('Number of Parameters : ',DTypeData^.ParamCount);
  234. Writeln('Parameter List : ');//,DTypeData^.ParamList);
  235. {$IFDEF delphibuiltin}
  236. With DTypeData^ do
  237. SetArrayParameter(@DTypeData^.ParamList,ParamCount,MethodKind);
  238. {$ELSE}
  239. //================================
  240. Definition:='(';
  241. // Definition := Definition+'(';
  242. CurrentParamPosition := 0;
  243. for i:= 1 to DTypeData^.ParamCount do
  244. begin
  245. { First Handle the ParamFlag }
  246. Flag:=byte(DTypeData^.ParamList[CurrentParamPosition]);
  247. Flags:=TParamFlags(Flag);
  248. writeln('ord(Flags):',ord(DTypeData^.ParamList[CurrentParamPosition]));
  249. // For i:= 1 to NumI do
  250. // begin
  251. if pfVar in Flags
  252. then Definition := Definition+('var ');
  253. if pfconst in Flags
  254. then Definition := Definition+('const ');
  255. if pfArray in Flags
  256. then Definition := Definition+('array of ');
  257. if pfAddress in Flags
  258. then Definition := Definition+('adresse ?'); // si Self ?
  259. if pfReference in Flags
  260. then Definition := Definition+('reference ?'); // ??
  261. if pfout in Flags
  262. then Definition := Definition+('out ');
  263. { Next char is the length of the ParamName}
  264. inc(CurrentParamPosition);
  265. ParamNameLength := ord( DTypeData^.ParamList[CurrentParamPosition]);
  266. { Next extract the Name of the Parameter }
  267. ParamName := '';
  268. for j := CurrentParamPosition + 1 to CurrentParamPosition + ParamNameLength do
  269. ParamName := ParamName + DTypeData^.ParamList[j];
  270. CurrentParamPosition := CurrentParamPosition + ParamNameLength;
  271. { Next extract the Type of the Parameter }
  272. inc(CurrentParamPosition);
  273. ParamNameLength := ord( DTypeData^.ParamList[CurrentParamPosition]);
  274. writeln('Length type:',ParamNameLength);
  275. TypeName := '';
  276. for j := CurrentParamPosition + 1 to CurrentParamPosition + ParamNameLength do
  277. TypeName := TypeName + DTypeData^.ParamList[j];
  278. CurrentParamPosition := CurrentParamPosition +
  279. ParamNameLength + 1;
  280. writeln('ParamName:',i,':', ParamName);
  281. writeln('TypeName:',i,':', TypeName);
  282. Definition := Format('%s%s: %s', [Definition, ParamName, TypeName]);
  283. If I<DTypeData^.ParamCount then Definition := Definition + '; '
  284. end;
  285. if DTypeData^.MethodKind = mkFunction then
  286. begin
  287. ParamNameLength := ord( DTypeData^.ParamList[CurrentParamPosition]);
  288. Fu_ResultType := '';
  289. for j := CurrentParamPosition + 1 to CurrentParamPosition + ParamNameLength do
  290. Fu_ResultType := Fu_ResultType + DTypeData^.ParamList[j];
  291. end
  292. else
  293. Fu_ResultType:='';
  294. // end;
  295. Definition := Definition + ')';
  296. if Fu_ResultType<>'' then
  297. Definition := Format('%s: %s', [Definition, Fu_ResultType]);
  298. Definition := Definition+' of object;';
  299. //=================================
  300. // Build the definion of method
  301. Writeln(PropTypeZ+' '+Definition);
  302. if ((PropTypeZ+' '+Definition) <> expectedresult) then
  303. begin
  304. writeln(expectedresult);
  305. halt(1);
  306. end;
  307. {$ENDIF}
  308. {$IFDEF delphibuiltin}
  309. Writeln(PropTypeZ+' '+BuildMethodDefinition(List_of_Param,DTypeData^.ParamCount));
  310. {$ENDIF}
  311. Method := GetMethodProp(OneObject, Informations.Name);
  312. if Method.Code <> NIL then
  313. begin
  314. Resultat:='';
  315. TBatch(Method)(Resultat);
  316. Writeln(Resultat);
  317. end;
  318. end;
  319. end;
  320. end;
  321. end;
  322. const
  323. expectedresults: array[0..6] of ansistring = (
  324. '',
  325. 'function (var array of reference ?Array1: AnsiString; const P: Pointer; out Out1: Int64): Int64 of object;',
  326. 'procedure (adresse ?Component1: TComponent; var adresse ?Component2: TComponent; adresse ?out Component3: TComponent; const adresse ?Component4: TComponent) of object;',
  327. 'function (array of reference ?A: Byte; const array of reference ?B: Byte; var array of reference ?C: Byte; array of reference ?out D: Byte): TComponent of object;',
  328. 'function (var S: AnsiString; const A: LongInt): Int64 of object;',
  329. 'function (const A: AnsiString; var Two: LongInt; adresse ?out Three: TMyObject; Four: PInteger; array of reference ?Five: Byte; Six: LongInt): AnsiString of object;',
  330. 'procedure (var S: AnsiString) of object;'
  331. );
  332. begin
  333. OneObject:=TMyObject.Create;
  334. OneObject.FP1:=3;
  335. //OneObject.OnTraitement:=Nil; // GetMethodProp => Method.Code=Nil
  336. {$IFDEF FPC}
  337. OneObject.OnTraitement:[email protected];//(vartrait1);
  338. {$ELSE}
  339. OneObject.OnTraitement:=OneObject.ProcNo1;//(vartrait1);
  340. {$ENDIF}
  341. // Get list properties
  342. NumI := GetPropList(TMyObject.ClassInfo, tkAny, @List_of_Prop);
  343. writeln('numi: ',numi);
  344. if (numi<>length(expectedresults)) then
  345. halt(44);
  346. for I := 0 to NumI-1 do
  347. begin
  348. Writeln('Propriete ',I+1,' = ',List_of_Prop[I]^.Name);
  349. DisplayDetails(List_of_Prop[I]^,expectedresults[i]);
  350. Writeln;
  351. end;
  352. { Other
  353. GetPropInfos(TMyObject.ClassInfo, @List_of_Prop);
  354. for I := 0 to GetTypeData(TMyObject.ClassInfo).PropCount-1 do
  355. begin
  356. Writeln('Property ',I+1,' = ',List_of_Prop[I]^.Name);
  357. DisplayDetails(List_of_Prop[I]^);
  358. end;
  359. }
  360. OneObject.Free;
  361. end.