rtti.pp 103 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (C) 2013 Joost van der Sluis [email protected]
  4. member of the Free Pascal development team.
  5. Extended RTTI compatibility unit
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. }
  12. unit Rtti experimental;
  13. {$mode objfpc}{$H+}
  14. {$modeswitch advancedrecords}
  15. {$goto on}
  16. {$Assertions on}
  17. { Note: since the Lazarus IDE is not yet capable of correctly handling generic
  18. functions it is best to define a InLazIDE define inside the IDE that disables
  19. the generic code for CodeTools. To do this do this:
  20. - go to Tools -> Codetools Defines Editor
  21. - go to Edit -> Insert Node Below -> Define Recurse
  22. - enter the following values:
  23. Name: InLazIDE
  24. Description: Define InLazIDE everywhere
  25. Variable: InLazIDE
  26. Value from text: 1
  27. }
  28. {$ifdef InLazIDE}
  29. {$define NoGenericMethods}
  30. {$endif}
  31. interface
  32. uses
  33. Classes,
  34. SysUtils,
  35. typinfo;
  36. type
  37. TRttiObject = class;
  38. TRttiType = class;
  39. TRttiMethod = class;
  40. TRttiProperty = class;
  41. TRttiInstanceType = class;
  42. TFunctionCallCallback = class
  43. protected
  44. function GetCodeAddress: CodePointer; virtual; abstract;
  45. public
  46. property CodeAddress: CodePointer read GetCodeAddress;
  47. end;
  48. TFunctionCallFlag = (
  49. fcfStatic
  50. );
  51. TFunctionCallFlags = set of TFunctionCallFlag;
  52. TFunctionCallParameterInfo = record
  53. ParamType: PTypeInfo;
  54. ParamFlags: TParamFlags;
  55. ParaLocs: PParameterLocations;
  56. end;
  57. IValueData = interface
  58. ['{1338B2F3-2C21-4798-A641-CA2BC5BF2396}']
  59. procedure ExtractRawData(ABuffer: pointer);
  60. procedure ExtractRawDataNoCopy(ABuffer: pointer);
  61. function GetDataSize: SizeInt;
  62. function GetReferenceToRawData: pointer;
  63. end;
  64. TValueData = record
  65. FTypeInfo: PTypeInfo;
  66. FValueData: IValueData;
  67. case integer of
  68. 0: (FAsUByte: Byte);
  69. 1: (FAsUWord: Word);
  70. 2: (FAsULong: LongWord);
  71. 3: (FAsObject: Pointer);
  72. 4: (FAsClass: TClass);
  73. 5: (FAsSByte: Shortint);
  74. 6: (FAsSWord: Smallint);
  75. 7: (FAsSLong: LongInt);
  76. 8: (FAsSingle: Single);
  77. 9: (FAsDouble: Double);
  78. 10: (FAsExtended: Extended);
  79. 11: (FAsComp: Comp);
  80. 12: (FAsCurr: Currency);
  81. 13: (FAsUInt64: QWord);
  82. 14: (FAsSInt64: Int64);
  83. 15: (FAsMethod: TMethod);
  84. 16: (FAsPointer: Pointer);
  85. { FPC addition for open arrays }
  86. 17: (FArrLength: SizeInt; FElSize: SizeInt);
  87. end;
  88. { TValue }
  89. TValue = record
  90. private
  91. FData: TValueData;
  92. function GetDataSize: SizeInt;
  93. function GetTypeDataProp: PTypeData; inline;
  94. function GetTypeInfo: PTypeInfo; inline;
  95. function GetTypeKind: TTypeKind; inline;
  96. function GetIsEmpty: boolean; inline;
  97. public
  98. class function Empty: TValue; static;
  99. class procedure Make(ABuffer: pointer; ATypeInfo: PTypeInfo; out result: TValue); static;
  100. { Note: a TValue based on an open array is only valid until the routine having the open array parameter is left! }
  101. class procedure MakeOpenArray(AArray: Pointer; ALength: SizeInt; ATypeInfo: PTypeInfo; out Result: TValue); static;
  102. {$ifndef NoGenericMethods}
  103. generic class function From<T>(constref aValue: T): TValue; static; inline;
  104. { Note: a TValue based on an open array is only valid until the routine having the open array parameter is left! }
  105. generic class function FromOpenArray<T>(constref aValue: array of T): TValue; static; inline;
  106. {$endif}
  107. function IsArray: boolean; inline;
  108. function IsOpenArray: Boolean; inline;
  109. function AsString: string; inline;
  110. function AsUnicodeString: UnicodeString;
  111. function AsAnsiString: AnsiString;
  112. function AsExtended: Extended;
  113. function IsClass: boolean; inline;
  114. function AsClass: TClass;
  115. function IsObject: boolean; inline;
  116. function AsObject: TObject;
  117. function IsOrdinal: boolean; inline;
  118. function AsOrdinal: Int64;
  119. function AsBoolean: boolean;
  120. function AsCurrency: Currency;
  121. function AsInteger: Integer;
  122. function AsInt64: Int64;
  123. function AsUInt64: QWord;
  124. function AsInterface: IInterface;
  125. function ToString: String;
  126. function GetArrayLength: SizeInt;
  127. function GetArrayElement(AIndex: SizeInt): TValue;
  128. procedure SetArrayElement(AIndex: SizeInt; constref AValue: TValue);
  129. function IsType(ATypeInfo: PTypeInfo): boolean; inline;
  130. function TryAsOrdinal(out AResult: int64): boolean;
  131. function GetReferenceToRawData: Pointer;
  132. procedure ExtractRawData(ABuffer: Pointer);
  133. procedure ExtractRawDataNoCopy(ABuffer: Pointer);
  134. class operator := (const AValue: String): TValue; inline;
  135. class operator := (AValue: LongInt): TValue; inline;
  136. class operator := (AValue: Single): TValue; inline;
  137. class operator := (AValue: Double): TValue; inline;
  138. {$ifdef FPC_HAS_TYPE_EXTENDED}
  139. class operator := (AValue: Extended): TValue; inline;
  140. {$endif}
  141. class operator := (AValue: Currency): TValue; inline;
  142. class operator := (AValue: Int64): TValue; inline;
  143. class operator := (AValue: QWord): TValue; inline;
  144. class operator := (AValue: TObject): TValue; inline;
  145. class operator := (AValue: TClass): TValue; inline;
  146. class operator := (AValue: Boolean): TValue; inline;
  147. property DataSize: SizeInt read GetDataSize;
  148. property Kind: TTypeKind read GetTypeKind;
  149. property TypeData: PTypeData read GetTypeDataProp;
  150. property TypeInfo: PTypeInfo read GetTypeInfo;
  151. property IsEmpty: boolean read GetIsEmpty;
  152. end;
  153. TValueArray = specialize TArray<TValue>;
  154. { TRttiContext }
  155. TRttiContext = record
  156. private
  157. FContextToken: IInterface;
  158. function GetByHandle(AHandle: Pointer): TRttiObject;
  159. procedure AddObject(AObject: TRttiObject);
  160. public
  161. class function Create: TRttiContext; static;
  162. procedure Free;
  163. function GetType(ATypeInfo: PTypeInfo): TRttiType;
  164. function GetType(AClass: TClass): TRttiType;
  165. //function GetTypes: specialize TArray<TRttiType>;
  166. end;
  167. { TRttiObject }
  168. TRttiObject = class abstract
  169. protected
  170. function GetHandle: Pointer; virtual; abstract;
  171. public
  172. property Handle: Pointer read GetHandle;
  173. end;
  174. { TRttiNamedObject }
  175. TRttiNamedObject = class(TRttiObject)
  176. protected
  177. function GetName: string; virtual;
  178. public
  179. property Name: string read GetName;
  180. end;
  181. { TRttiType }
  182. TRttiType = class(TRttiNamedObject)
  183. private
  184. FTypeInfo: PTypeInfo;
  185. FMethods: specialize TArray<TRttiMethod>;
  186. function GetAsInstance: TRttiInstanceType;
  187. protected
  188. FTypeData: PTypeData;
  189. function GetName: string; override;
  190. function GetHandle: Pointer; override;
  191. function GetIsInstance: boolean; virtual;
  192. function GetIsManaged: boolean; virtual;
  193. function GetIsOrdinal: boolean; virtual;
  194. function GetIsRecord: boolean; virtual;
  195. function GetIsSet: boolean; virtual;
  196. function GetTypeKind: TTypeKind; virtual;
  197. function GetTypeSize: integer; virtual;
  198. function GetBaseType: TRttiType; virtual;
  199. public
  200. constructor Create(ATypeInfo : PTypeInfo);
  201. function GetProperties: specialize TArray<TRttiProperty>; virtual;
  202. function GetProperty(const AName: string): TRttiProperty; virtual;
  203. function GetMethods: specialize TArray<TRttiMethod>; virtual;
  204. function GetMethod(const aName: String): TRttiMethod; virtual;
  205. function GetDeclaredMethods: specialize TArray<TRttiMethod>; virtual;
  206. property IsInstance: boolean read GetIsInstance;
  207. property isManaged: boolean read GetIsManaged;
  208. property IsOrdinal: boolean read GetIsOrdinal;
  209. property IsRecord: boolean read GetIsRecord;
  210. property IsSet: boolean read GetIsSet;
  211. property BaseType: TRttiType read GetBaseType;
  212. property AsInstance: TRttiInstanceType read GetAsInstance;
  213. property TypeKind: TTypeKind read GetTypeKind;
  214. property TypeSize: integer read GetTypeSize;
  215. end;
  216. { TRttiFloatType }
  217. TRttiFloatType = class(TRttiType)
  218. private
  219. function GetFloatType: TFloatType;
  220. public
  221. property FloatType: TFloatType read GetFloatType;
  222. end;
  223. TRttiStringKind = (skShortString, skAnsiString, skWideString, skUnicodeString);
  224. { TRttiStringType }
  225. TRttiStringType = class(TRttiType)
  226. private
  227. function GetStringKind: TRttiStringKind;
  228. public
  229. property StringKind: TRttiStringKind read GetStringKind;
  230. end;
  231. TRttiPointerType = class(TRttiType)
  232. private
  233. function GetReferredType: TRttiType;
  234. public
  235. property ReferredType: TRttiType read GetReferredType;
  236. end;
  237. { TRttiMember }
  238. TMemberVisibility=(mvPrivate, mvProtected, mvPublic, mvPublished);
  239. TRttiMember = class(TRttiNamedObject)
  240. private
  241. FParent: TRttiType;
  242. protected
  243. function GetVisibility: TMemberVisibility; virtual;
  244. public
  245. constructor Create(AParent: TRttiType);
  246. property Visibility: TMemberVisibility read GetVisibility;
  247. property Parent: TRttiType read FParent;
  248. end;
  249. { TRttiProperty }
  250. TRttiProperty = class(TRttiMember)
  251. private
  252. FPropInfo: PPropInfo;
  253. function GetPropertyType: TRttiType;
  254. function GetIsWritable: boolean;
  255. function GetIsReadable: boolean;
  256. protected
  257. function GetVisibility: TMemberVisibility; override;
  258. function GetName: string; override;
  259. function GetHandle: Pointer; override;
  260. public
  261. constructor Create(AParent: TRttiType; APropInfo: PPropInfo);
  262. function GetValue(Instance: pointer): TValue;
  263. procedure SetValue(Instance: pointer; const AValue: TValue);
  264. property PropertyType: TRttiType read GetPropertyType;
  265. property IsReadable: boolean read GetIsReadable;
  266. property IsWritable: boolean read GetIsWritable;
  267. property Visibility: TMemberVisibility read GetVisibility;
  268. end;
  269. TRttiParameter = class(TRttiNamedObject)
  270. private
  271. FString: String;
  272. protected
  273. function GetParamType: TRttiType; virtual; abstract;
  274. function GetFlags: TParamFlags; virtual; abstract;
  275. public
  276. property ParamType: TRttiType read GetParamType;
  277. property Flags: TParamFlags read GetFlags;
  278. function ToString: String; override;
  279. end;
  280. TMethodImplementationCallbackMethod = procedure(aUserData: Pointer; const aArgs: TValueArray; out aResult: TValue) of object;
  281. TMethodImplementationCallbackProc = procedure(aUserData: Pointer; const aArgs: TValueArray; out aResult: TValue);
  282. TMethodImplementation = class
  283. private
  284. fLowLevelCallback: TFunctionCallCallback;
  285. fCallbackProc: TMethodImplementationCallbackProc;
  286. fCallbackMethod: TMethodImplementationCallbackMethod;
  287. fArgs: specialize TArray<TFunctionCallParameterInfo>;
  288. fArgLen: SizeInt;
  289. fRefArgs: specialize TArray<SizeInt>;
  290. fFlags: TFunctionCallFlags;
  291. fResult: PTypeInfo;
  292. fCC: TCallConv;
  293. function GetCodeAddress: CodePointer;
  294. procedure InitArgs;
  295. procedure HandleCallback(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer);
  296. constructor Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackMethod);
  297. constructor Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackProc);
  298. public
  299. constructor Create;
  300. destructor Destroy; override;
  301. property CodeAddress: CodePointer read GetCodeAddress;
  302. end;
  303. TRttiInvokableType = class(TRttiType)
  304. protected
  305. function GetParameters(aWithHidden: Boolean): specialize TArray<TRttiParameter>; virtual; abstract;
  306. function GetCallingConvention: TCallConv; virtual; abstract;
  307. function GetReturnType: TRttiType; virtual; abstract;
  308. function GetFlags: TFunctionCallFlags; virtual; abstract;
  309. public type
  310. TCallbackMethod = procedure(aInvokable: TRttiInvokableType; const aArgs: TValueArray; out aResult: TValue) of object;
  311. TCallbackProc = procedure(aInvokable: TRttiInvokableType; const aArgs: TValueArray; out aResult: TValue);
  312. public
  313. function GetParameters: specialize TArray<TRttiParameter>; inline;
  314. property CallingConvention: TCallConv read GetCallingConvention;
  315. property ReturnType: TRttiType read GetReturnType;
  316. function Invoke(const aProcOrMeth: TValue; const aArgs: array of TValue): TValue; virtual; abstract;
  317. { Note: once "reference to" is supported these will be replaced by a single method }
  318. function CreateImplementation(aCallback: TCallbackMethod): TMethodImplementation;
  319. function CreateImplementation(aCallback: TCallbackProc): TMethodImplementation;
  320. end;
  321. TRttiMethodType = class(TRttiInvokableType)
  322. private
  323. FCallConv: TCallConv;
  324. FReturnType: TRttiType;
  325. FParams, FParamsAll: specialize TArray<TRttiParameter>;
  326. protected
  327. function GetParameters(aWithHidden: Boolean): specialize TArray<TRttiParameter>; override;
  328. function GetCallingConvention: TCallConv; override;
  329. function GetReturnType: TRttiType; override;
  330. function GetFlags: TFunctionCallFlags; override;
  331. public
  332. function Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue; override;
  333. end;
  334. TRttiProcedureType = class(TRttiInvokableType)
  335. private
  336. FParams, FParamsAll: specialize TArray<TRttiParameter>;
  337. protected
  338. function GetParameters(aWithHidden: Boolean): specialize TArray<TRttiParameter>; override;
  339. function GetCallingConvention: TCallConv; override;
  340. function GetReturnType: TRttiType; override;
  341. function GetFlags: TFunctionCallFlags; override;
  342. public
  343. function Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue; override;
  344. end;
  345. TDispatchKind = (
  346. dkStatic,
  347. dkVtable,
  348. dkDynamic,
  349. dkMessage,
  350. dkInterface,
  351. { the following are FPC-only and will be moved should Delphi add more }
  352. dkMessageString
  353. );
  354. TRttiMethod = class(TRttiMember)
  355. private
  356. FString: String;
  357. protected
  358. function GetCallingConvention: TCallConv; virtual; abstract;
  359. function GetCodeAddress: CodePointer; virtual; abstract;
  360. function GetDispatchKind: TDispatchKind; virtual; abstract;
  361. function GetHasExtendedInfo: Boolean; virtual;
  362. function GetIsClassMethod: Boolean; virtual; abstract;
  363. function GetIsConstructor: Boolean; virtual; abstract;
  364. function GetIsDestructor: Boolean; virtual; abstract;
  365. function GetIsStatic: Boolean; virtual; abstract;
  366. function GetMethodKind: TMethodKind; virtual; abstract;
  367. function GetReturnType: TRttiType; virtual; abstract;
  368. function GetVirtualIndex: SmallInt; virtual; abstract;
  369. function GetParameters(aWithHidden: Boolean): specialize TArray<TRttiParameter>; virtual; abstract;
  370. public
  371. property CallingConvention: TCallConv read GetCallingConvention;
  372. property CodeAddress: CodePointer read GetCodeAddress;
  373. property DispatchKind: TDispatchKind read GetDispatchKind;
  374. property HasExtendedInfo: Boolean read GetHasExtendedInfo;
  375. property IsClassMethod: Boolean read GetIsClassMethod;
  376. property IsConstructor: Boolean read GetIsConstructor;
  377. property IsDestructor: Boolean read GetIsDestructor;
  378. property IsStatic: Boolean read GetIsStatic;
  379. property MethodKind: TMethodKind read GetMethodKind;
  380. property ReturnType: TRttiType read GetReturnType;
  381. property VirtualIndex: SmallInt read GetVirtualIndex;
  382. function ToString: String; override;
  383. function GetParameters: specialize TArray<TRttiParameter>; inline;
  384. function Invoke(aInstance: TObject; const aArgs: array of TValue): TValue;
  385. function Invoke(aInstance: TClass; const aArgs: array of TValue): TValue;
  386. function Invoke(aInstance: TValue; const aArgs: array of TValue): TValue;
  387. end;
  388. TRttiStructuredType = class(TRttiType)
  389. end;
  390. TInterfaceType = (
  391. itRefCounted, { aka COM interface }
  392. itRaw { aka CORBA interface }
  393. );
  394. TRttiInterfaceType = class(TRttiType)
  395. private
  396. fDeclaredMethods: specialize TArray<TRttiMethod>;
  397. protected
  398. function IntfMethodCount: Word;
  399. function MethodTable: PIntfMethodTable; virtual; abstract;
  400. function GetBaseType: TRttiType; override;
  401. function GetIntfBaseType: TRttiInterfaceType; virtual; abstract;
  402. function GetDeclaringUnitName: String; virtual; abstract;
  403. function GetGUID: TGUID; virtual; abstract;
  404. function GetGUIDStr: String; virtual;
  405. function GetIntfFlags: TIntfFlags; virtual; abstract;
  406. function GetIntfType: TInterfaceType; virtual; abstract;
  407. public
  408. property BaseType: TRttiInterfaceType read GetIntfBaseType;
  409. property DeclaringUnitName: String read GetDeclaringUnitName;
  410. property GUID: TGUID read GetGUID;
  411. property GUIDStr: String read GetGUIDStr;
  412. property IntfFlags: TIntfFlags read GetIntfFlags;
  413. property IntfType: TInterfaceType read GetIntfType;
  414. function GetDeclaredMethods: specialize TArray<TRttiMethod>; override;
  415. end;
  416. { TRttiInstanceType }
  417. TRttiInstanceType = class(TRttiStructuredType)
  418. private
  419. FPropertiesResolved: Boolean;
  420. FProperties: specialize TArray<TRttiProperty>;
  421. function GetDeclaringUnitName: string;
  422. function GetMetaClassType: TClass;
  423. protected
  424. function GetIsInstance: boolean; override;
  425. function GetTypeSize: integer; override;
  426. function GetBaseType: TRttiType; override;
  427. public
  428. function GetProperties: specialize TArray<TRttiProperty>; override;
  429. property MetaClassType: TClass read GetMetaClassType;
  430. property DeclaringUnitName: string read GetDeclaringUnitName;
  431. end;
  432. EInsufficientRtti = class(Exception);
  433. EInvocationError = class(Exception);
  434. ENonPublicType = class(Exception);
  435. TFunctionCallParameter = record
  436. ValueRef: Pointer;
  437. ValueSize: SizeInt;
  438. Info: TFunctionCallParameterInfo;
  439. end;
  440. TFunctionCallParameterArray = specialize TArray<TFunctionCallParameter>;
  441. TFunctionCallProc = procedure(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer);
  442. TFunctionCallMethod = procedure(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer) of object;
  443. TFunctionCallManager = record
  444. Invoke: procedure(CodeAddress: CodePointer; const Args: TFunctionCallParameterArray; CallingConvention: TCallConv;
  445. ResultType: PTypeInfo; ResultValue: Pointer; Flags: TFunctionCallFlags);
  446. CreateCallbackProc: function(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  447. CreateCallbackMethod: function(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  448. end;
  449. TFunctionCallManagerArray = array[TCallConv] of TFunctionCallManager;
  450. TCallConvSet = set of TCallConv;
  451. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager; out aOldFuncCallMgr: TFunctionCallManager);
  452. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager);
  453. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  454. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager);
  455. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  456. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray);
  457. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  458. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray);
  459. procedure GetFunctionCallManager(aCallConv: TCallConv; out aFuncCallMgr: TFunctionCallManager);
  460. procedure GetFunctionCallManagers(aCallConvs: TCallConvSet; out aFuncCallMgrs: TFunctionCallManagerArray);
  461. procedure GetFunctionCallManagers(out aFuncCallMgrs: TFunctionCallManagerArray);
  462. function Invoke(aCodeAddress: CodePointer; const aArgs: TValueArray; aCallConv: TCallConv;
  463. aResultType: PTypeInfo; aIsStatic: Boolean; aIsConstructor: Boolean): TValue;
  464. function CreateCallbackProc(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  465. function CreateCallbackMethod(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  466. function IsManaged(TypeInfo: PTypeInfo): boolean;
  467. {$ifndef InLazIDE}
  468. generic function OpenArrayToDynArrayValue<T>(constref aArray: array of T): TValue;
  469. {$endif}
  470. { these resource strings are needed by units implementing function call managers }
  471. resourcestring
  472. SErrInvokeNotImplemented = 'Invoke functionality is not implemented';
  473. SErrInvokeResultTypeNoValue = 'Function has a result type, but no result pointer provided';
  474. SErrInvokeFailed = 'Invoke call failed';
  475. SErrCallbackNotImplented = 'Callback functionality is not implemented';
  476. SErrCallConvNotSupported = 'Calling convention not supported: %s';
  477. SErrTypeKindNotSupported = 'Type kind is not supported: %s';
  478. SErrCallbackHandlerNil = 'Callback handler is Nil';
  479. SErrMissingSelfParam = 'Missing self parameter';
  480. implementation
  481. uses
  482. {$ifdef windows}
  483. Windows,
  484. {$endif}
  485. fgl;
  486. type
  487. { TRttiPool }
  488. TRttiPool = class
  489. private type
  490. TRttiObjectMap = specialize TFPGMap<Pointer, TRttiObject>;
  491. private
  492. FObjectMap: TRttiObjectMap;
  493. FTypesList: specialize TArray<TRttiType>;
  494. FTypeCount: LongInt;
  495. FLock: TRTLCriticalSection;
  496. public
  497. function GetTypes: specialize TArray<TRttiType>;
  498. function GetType(ATypeInfo: PTypeInfo): TRttiType;
  499. function GetByHandle(aHandle: Pointer): TRttiObject;
  500. procedure AddObject(aObject: TRttiObject);
  501. constructor Create;
  502. destructor Destroy; override;
  503. end;
  504. IPooltoken = interface
  505. ['{3CDB3CE9-AB55-CBAA-7B9D-2F3BB1CF5AF8}']
  506. function RttiPool: TRttiPool;
  507. end;
  508. { TPoolToken }
  509. TPoolToken = class(TInterfacedObject, IPooltoken)
  510. public
  511. constructor Create;
  512. destructor Destroy; override;
  513. function RttiPool: TRttiPool;
  514. end;
  515. { TValueDataIntImpl }
  516. TValueDataIntImpl = class(TInterfacedObject, IValueData)
  517. private
  518. FBuffer: Pointer;
  519. FDataSize: SizeInt;
  520. FTypeInfo: PTypeInfo;
  521. FIsCopy: Boolean;
  522. FUseAddRef: Boolean;
  523. public
  524. constructor CreateCopy(ACopyFromBuffer: Pointer; ALen: SizeInt; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  525. constructor CreateRef(AData: Pointer; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  526. destructor Destroy; override;
  527. procedure ExtractRawData(ABuffer: pointer);
  528. procedure ExtractRawDataNoCopy(ABuffer: pointer);
  529. function GetDataSize: SizeInt;
  530. function GetReferenceToRawData: pointer;
  531. end;
  532. TRttiRefCountedInterfaceType = class(TRttiInterfaceType)
  533. private
  534. function IntfData: PInterfaceData; inline;
  535. protected
  536. function MethodTable: PIntfMethodTable; override;
  537. function GetIntfBaseType: TRttiInterfaceType; override;
  538. function GetDeclaringUnitName: String; override;
  539. function GetGUID: TGUID; override;
  540. function GetIntfFlags: TIntfFlags; override;
  541. function GetIntfType: TInterfaceType; override;
  542. end;
  543. TRttiRawInterfaceType = class(TRttiInterfaceType)
  544. private
  545. function IntfData: PInterfaceRawData; inline;
  546. protected
  547. function MethodTable: PIntfMethodTable; override;
  548. function GetIntfBaseType: TRttiInterfaceType; override;
  549. function GetDeclaringUnitName: String; override;
  550. function GetGUID: TGUID; override;
  551. function GetGUIDStr: String; override;
  552. function GetIntfFlags: TIntfFlags; override;
  553. function GetIntfType: TInterfaceType; override;
  554. end;
  555. TRttiVmtMethodParameter = class(TRttiParameter)
  556. private
  557. FVmtMethodParam: PVmtMethodParam;
  558. protected
  559. function GetHandle: Pointer; override;
  560. function GetName: String; override;
  561. function GetFlags: TParamFlags; override;
  562. function GetParamType: TRttiType; override;
  563. public
  564. constructor Create(AVmtMethodParam: PVmtMethodParam);
  565. end;
  566. TRttiMethodTypeParameter = class(TRttiParameter)
  567. private
  568. fHandle: Pointer;
  569. fName: String;
  570. fFlags: TParamFlags;
  571. fType: PTypeInfo;
  572. protected
  573. function GetHandle: Pointer; override;
  574. function GetName: String; override;
  575. function GetFlags: TParamFlags; override;
  576. function GetParamType: TRttiType; override;
  577. public
  578. constructor Create(aHandle: Pointer; const aName: String; aFlags: TParamFlags; aType: PTypeInfo);
  579. end;
  580. TRttiIntfMethod = class(TRttiMethod)
  581. private
  582. FIntfMethodEntry: PIntfMethodEntry;
  583. FIndex: SmallInt;
  584. FParams, FParamsAll: specialize TArray<TRttiParameter>;
  585. protected
  586. function GetHandle: Pointer; override;
  587. function GetName: String; override;
  588. function GetCallingConvention: TCallConv; override;
  589. function GetCodeAddress: CodePointer; override;
  590. function GetDispatchKind: TDispatchKind; override;
  591. function GetHasExtendedInfo: Boolean; override;
  592. function GetIsClassMethod: Boolean; override;
  593. function GetIsConstructor: Boolean; override;
  594. function GetIsDestructor: Boolean; override;
  595. function GetIsStatic: Boolean; override;
  596. function GetMethodKind: TMethodKind; override;
  597. function GetReturnType: TRttiType; override;
  598. function GetVirtualIndex: SmallInt; override;
  599. function GetParameters(aWithHidden: Boolean): specialize TArray<TRttiParameter>; override;
  600. public
  601. constructor Create(AParent: TRttiType; AIntfMethodEntry: PIntfMethodEntry; AIndex: SmallInt);
  602. end;
  603. resourcestring
  604. SErrUnableToGetValueForType = 'Unable to get value for type %s';
  605. SErrUnableToSetValueForType = 'Unable to set value for type %s';
  606. SErrInvalidTypecast = 'Invalid class typecast';
  607. SErrRttiObjectNoHandle = 'RTTI object instance has no valid handle property';
  608. SErrRttiObjectAlreadyRegistered = 'A RTTI object with handle 0x%x is already registered';
  609. SErrInvokeInsufficientRtti = 'Insufficient RTTI to invoke function';
  610. SErrInvokeStaticNoSelf = 'Static function must not be called with in an instance: %s';
  611. SErrInvokeNotStaticNeedsSelf = 'Non static function must be called with an instance: %s';
  612. SErrInvokeClassMethodClassSelf = 'Class method needs to be called with a class type: %s';
  613. SErrInvokeArrayArgExpected = 'Array argument expected for parameter %s of method %s';
  614. SErrInvokeArgInvalidType = 'Invalid type of argument for parameter %s of method %s';
  615. SErrInvokeArgCount = 'Invalid argument count for method %s; expected %d, but got %d';
  616. SErrInvokeNoCodeAddr = 'Failed to determine code address for method: %s';
  617. SErrInvokeRttiDataError = 'The RTTI data is inconsistent for method: %s';
  618. SErrInvokeCallableNotProc = 'The callable value is not a procedure variable for: %s';
  619. SErrInvokeCallableNotMethod = 'The callable value is not a method variable for: %s';
  620. SErrMethodImplNoCallback = 'No callback specified for method implementation';
  621. SErrMethodImplInsufficientRtti = 'Insufficient RTTI to create method implementation';
  622. SErrMethodImplCreateFailed = 'Failed to create method implementation';
  623. SErrMethodImplCreateNoArg = 'TMethodImplementation can not be created this way';
  624. var
  625. PoolRefCount : integer;
  626. GRttiPool : TRttiPool;
  627. FuncCallMgr: TFunctionCallManagerArray;
  628. function AllocateMemory(aSize: PtrUInt): Pointer;
  629. begin
  630. {$IF DEFINED(WINDOWS)}
  631. Result := VirtualAlloc(Nil, aSize, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
  632. {$ELSE}
  633. Result := GetMem(aSize);
  634. {$ENDIF}
  635. end;
  636. function ProtectMemory(aPtr: Pointer; aSize: PtrUInt; aExecutable: Boolean): Boolean;
  637. {$IF DEFINED(WINDOWS)}
  638. var
  639. oldprot: DWORD;
  640. {$ENDIF}
  641. begin
  642. {$IF DEFINED(WINDOWS)}
  643. if aExecutable then
  644. Result := VirtualProtect(aPtr, aSize, PAGE_EXECUTE_READ, oldprot)
  645. else
  646. Result := VirtualProtect(aPtr, aSize, PAGE_READWRITE, oldprot);
  647. {$ELSE}
  648. Result := True;
  649. {$ENDIF}
  650. end;
  651. procedure FreeMemory(aPtr: Pointer);
  652. begin
  653. {$IF DEFINED(WINDOWS)}
  654. VirtualFree(aPtr, 0, MEM_RELEASE);
  655. {$ELSE}
  656. FreeMem(aPtr);
  657. {$ENDIF}
  658. end;
  659. function CCToStr(aCC: TCallConv): String; inline;
  660. begin
  661. WriteStr(Result, aCC);
  662. end;
  663. procedure NoInvoke(aCodeAddress: CodePointer; const aArgs: TFunctionCallParameterArray; aCallConv: TCallConv;
  664. aResultType: PTypeInfo; aResultValue: Pointer; aFlags: TFunctionCallFlags);
  665. begin
  666. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  667. end;
  668. function NoCreateCallbackProc(aFunc: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  669. begin
  670. Result := Nil;
  671. raise ENotImplemented.Create(SErrCallbackNotImplented);
  672. end;
  673. function NoCreateCallbackMethod(aFunc: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  674. begin
  675. Result := Nil;
  676. raise ENotImplemented.Create(SErrCallbackNotImplented);
  677. end;
  678. const
  679. NoFunctionCallManager: TFunctionCallManager = (
  680. Invoke: @NoInvoke;
  681. CreateCallbackProc: @NoCreateCallbackProc;
  682. CreateCallbackMethod: @NoCreateCallbackMethod;
  683. );
  684. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager;
  685. out aOldFuncCallMgr: TFunctionCallManager);
  686. begin
  687. aOldFuncCallMgr := FuncCallMgr[aCallConv];
  688. FuncCallMgr[aCallConv] := aFuncCallMgr;
  689. end;
  690. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager);
  691. var
  692. dummy: TFunctionCallManager;
  693. begin
  694. SetFunctionCallManager(aCallConv, aFuncCallMgr, dummy);
  695. end;
  696. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager;
  697. out aOldFuncCallMgrs: TFunctionCallManagerArray);
  698. var
  699. cc: TCallConv;
  700. begin
  701. for cc := Low(TCallConv) to High(TCallConv) do
  702. if cc in aCallConvs then begin
  703. aOldFuncCallMgrs[cc] := FuncCallMgr[cc];
  704. FuncCallMgr[cc] := aFuncCallMgr;
  705. end else
  706. aOldFuncCallMgrs[cc] := Default(TFunctionCallManager);
  707. end;
  708. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager);
  709. var
  710. dummy: TFunctionCallManagerArray;
  711. begin
  712. SetFunctionCallManager(aCallConvs, aFuncCallMgr, dummy);
  713. end;
  714. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  715. var
  716. cc: TCallConv;
  717. begin
  718. for cc := Low(TCallConv) to High(TCallConv) do
  719. if cc in aCallConvs then begin
  720. aOldFuncCallMgrs[cc] := FuncCallMgr[cc];
  721. FuncCallMgr[cc] := aFuncCallMgrs[cc];
  722. end else
  723. aOldFuncCallMgrs[cc] := Default(TFunctionCallManager);
  724. end;
  725. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray);
  726. var
  727. dummy: TFunctionCallManagerArray;
  728. begin
  729. SetFunctionCallManagers(aCallConvs, aFuncCallMgrs, dummy);
  730. end;
  731. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  732. begin
  733. aOldFuncCallMgrs := FuncCallMgr;
  734. FuncCallMgr := aFuncCallMgrs;
  735. end;
  736. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray);
  737. var
  738. dummy: TFunctionCallManagerArray;
  739. begin
  740. SetFunctionCallManagers(aFuncCallMgrs, dummy);
  741. end;
  742. procedure GetFunctionCallManager(aCallConv: TCallConv; out aFuncCallMgr: TFunctionCallManager);
  743. begin
  744. aFuncCallMgr := FuncCallMgr[aCallConv];
  745. end;
  746. procedure GetFunctionCallManagers(aCallConvs: TCallConvSet; out aFuncCallMgrs: TFunctionCallManagerArray);
  747. var
  748. cc: TCallConv;
  749. begin
  750. for cc := Low(TCallConv) to High(TCallConv) do
  751. if cc in aCallConvs then
  752. aFuncCallMgrs[cc] := FuncCallMgr[cc]
  753. else
  754. aFuncCallMgrs[cc] := Default(TFunctionCallManager);
  755. end;
  756. procedure GetFunctionCallManagers(out aFuncCallMgrs: TFunctionCallManagerArray);
  757. begin
  758. aFuncCallMgrs := FuncCallMgr;
  759. end;
  760. procedure InitDefaultFunctionCallManager;
  761. var
  762. cc: TCallConv;
  763. begin
  764. for cc := Low(TCallConv) to High(TCallConv) do
  765. FuncCallMgr[cc] := NoFunctionCallManager;
  766. end;
  767. function Invoke(aCodeAddress: CodePointer; const aArgs: TValueArray;
  768. aCallConv: TCallConv; aResultType: PTypeInfo; aIsStatic: Boolean;
  769. aIsConstructor: Boolean): TValue;
  770. var
  771. funcargs: TFunctionCallParameterArray;
  772. i: LongInt;
  773. flags: TFunctionCallFlags;
  774. begin
  775. { sanity check }
  776. if not Assigned(FuncCallMgr[aCallConv].Invoke) then
  777. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  778. { ToDo: handle IsConstructor }
  779. if aIsConstructor then
  780. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  781. flags := [];
  782. if aIsStatic then
  783. Include(flags, fcfStatic)
  784. else if Length(aArgs) = 0 then
  785. raise EInvocationError.Create(SErrMissingSelfParam);
  786. SetLength(funcargs, Length(aArgs));
  787. for i := Low(aArgs) to High(aArgs) do begin
  788. funcargs[i - Low(aArgs) + Low(funcargs)].ValueRef := aArgs[i].GetReferenceToRawData;
  789. funcargs[i - Low(aArgs) + Low(funcargs)].ValueSize := aArgs[i].DataSize;
  790. funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParamType := aArgs[i].TypeInfo;
  791. funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParamFlags := [];
  792. funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParaLocs := Nil;
  793. end;
  794. if Assigned(aResultType) then
  795. TValue.Make(Nil, aResultType, Result)
  796. else
  797. Result := TValue.Empty;
  798. FuncCallMgr[aCallConv].Invoke(aCodeAddress, funcargs, aCallConv, aResultType, Result.GetReferenceToRawData, flags);
  799. end;
  800. function Invoke(const aName: String; aCodeAddress: CodePointer; aCallConv: TCallConv; aStatic: Boolean; aInstance: TValue; constref aArgs: array of TValue; const aParams: specialize TArray<TRttiParameter>; aReturnType: TRttiType): TValue;
  801. var
  802. arrparam, param: TRttiParameter;
  803. unhidden, highs, i: SizeInt;
  804. args: TFunctionCallParameterArray;
  805. highargs: array of SizeInt;
  806. restype: PTypeInfo;
  807. resptr: Pointer;
  808. mgr: TFunctionCallManager;
  809. flags: TFunctionCallFlags;
  810. begin
  811. mgr := FuncCallMgr[aCallConv];
  812. if not Assigned(mgr.Invoke) then
  813. raise EInvocationError.CreateFmt(SErrCallConvNotSupported, [CCToStr(aCallConv)]);
  814. if not Assigned(aCodeAddress) then
  815. raise EInvocationError.CreateFmt(SErrInvokeNoCodeAddr, [aName]);
  816. unhidden := 0;
  817. highs := 0;
  818. for param in aParams do begin
  819. if unhidden < Length(aArgs) then begin
  820. if pfArray in param.Flags then begin
  821. if Assigned(aArgs[unhidden].TypeInfo) and not aArgs[unhidden].IsArray and (aArgs[unhidden].Kind <> param.ParamType.TypeKind) then
  822. raise EInvocationError.CreateFmt(SErrInvokeArrayArgExpected, [param.Name, aName]);
  823. end else if not (pfHidden in param.Flags) then begin
  824. if aArgs[unhidden].Kind <> param.ParamType.TypeKind then
  825. raise EInvocationError.CreateFmt(SErrInvokeArgInvalidType, [param.Name, aName]);
  826. end;
  827. end;
  828. if not (pfHidden in param.Flags) then
  829. Inc(unhidden);
  830. if pfHigh in param.Flags then
  831. Inc(highs);
  832. end;
  833. if unhidden <> Length(aArgs) then
  834. raise EInvocationError.CreateFmt(SErrInvokeArgCount, [aName, unhidden, Length(aArgs)]);
  835. if Assigned(aReturnType) then begin
  836. TValue.Make(Nil, aReturnType.FTypeInfo, Result);
  837. resptr := Result.GetReferenceToRawData;
  838. restype := aReturnType.FTypeInfo;
  839. end else begin
  840. Result := TValue.Empty;
  841. resptr := Nil;
  842. restype := Nil;
  843. end;
  844. SetLength(highargs, highs);
  845. SetLength(args, Length(aParams));
  846. unhidden := 0;
  847. highs := 0;
  848. for i := 0 to High(aParams) do begin
  849. param := aParams[i];
  850. args[i].Info.ParamType := param.ParamType.FTypeInfo;
  851. args[i].Info.ParamFlags := param.Flags;
  852. args[i].Info.ParaLocs := Nil;
  853. if pfHidden in param.Flags then begin
  854. if pfSelf in param.Flags then
  855. args[i].ValueRef := aInstance.GetReferenceToRawData
  856. else if pfResult in param.Flags then begin
  857. if not Assigned(restype) then
  858. raise EInvocationError.CreateFmt(SErrInvokeRttiDataError, [aName]);
  859. args[i].ValueRef := resptr;
  860. restype := Nil;
  861. resptr := Nil;
  862. end else if pfHigh in param.Flags then begin
  863. { the corresponding array argument is the *previous* unhidden argument }
  864. if aArgs[unhidden - 1].IsArray then
  865. highargs[highs] := aArgs[unhidden - 1].GetArrayLength - 1
  866. else if not Assigned(aArgs[unhidden - 1].TypeInfo) then
  867. highargs[highs] := -1
  868. else
  869. highargs[highs] := 0;
  870. args[i].ValueRef := @highargs[highs];
  871. Inc(highs);
  872. end;
  873. end else begin
  874. if (pfArray in param.Flags) then begin
  875. if not Assigned(aArgs[unhidden].TypeInfo) then
  876. args[i].ValueRef := Nil
  877. else if aArgs[unhidden].Kind = tkDynArray then
  878. args[i].ValueRef := PPointer(aArgs[unhidden].GetReferenceToRawData)^
  879. else
  880. args[i].ValueRef := aArgs[unhidden].GetReferenceToRawData;
  881. end else
  882. args[i].ValueRef := aArgs[unhidden].GetReferenceToRawData;
  883. Inc(unhidden);
  884. end;
  885. end;
  886. flags := [];
  887. if aStatic then
  888. Include(flags, fcfStatic);
  889. mgr.Invoke(aCodeAddress, args, aCallConv, restype, resptr, flags);
  890. end;
  891. function CreateCallbackProc(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  892. begin
  893. if not Assigned(FuncCallMgr[aCallConv].CreateCallbackProc) then
  894. raise ENotImplemented.Create(SErrCallbackNotImplented);
  895. if not Assigned(aHandler) then
  896. raise EArgumentNilException.Create(SErrCallbackHandlerNil);
  897. Result := FuncCallMgr[aCallConv].CreateCallbackProc(aHandler, aCallConv, aArgs, aResultType, aFlags, aContext);
  898. end;
  899. function CreateCallbackMethod(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  900. begin
  901. if not Assigned(FuncCallMgr[aCallConv].CreateCallbackMethod) then
  902. raise ENotImplemented.Create(SErrCallbackNotImplented);
  903. if not Assigned(aHandler) then
  904. raise EArgumentNilException.Create(SErrCallbackHandlerNil);
  905. Result := FuncCallMgr[aCallConv].CreateCallbackMethod(aHandler, aCallConv, aArgs, aResultType, aFlags, aContext);
  906. end;
  907. function IsManaged(TypeInfo: PTypeInfo): boolean;
  908. begin
  909. if Assigned(TypeInfo) then
  910. case TypeInfo^.Kind of
  911. tkAString,
  912. tkLString,
  913. tkWString,
  914. tkUString,
  915. tkInterface,
  916. tkVariant,
  917. tkDynArray : Result := true;
  918. tkArray : Result := IsManaged(GetTypeData(TypeInfo)^.ArrayData.ElType);
  919. tkRecord,
  920. tkObject :
  921. with GetTypeData(TypeInfo)^.RecInitData^ do
  922. Result := (ManagedFieldCount > 0) or Assigned(ManagementOp);
  923. else
  924. Result := false;
  925. end
  926. else
  927. Result := false;
  928. end;
  929. {$ifndef InLazIDE}
  930. generic function OpenArrayToDynArrayValue<T>(constref aArray: array of T): TValue;
  931. var
  932. arr: specialize TArray<T>;
  933. i: SizeInt;
  934. begin
  935. SetLength(arr, Length(aArray));
  936. for i := 0 to High(aArray) do
  937. arr[i] := aArray[i];
  938. Result := TValue.specialize From<specialize TArray<T>>(arr);
  939. end;
  940. {$endif}
  941. { TRttiPointerType }
  942. function TRttiPointerType.GetReferredType: TRttiType;
  943. begin
  944. Result := GRttiPool.GetType(FTypeData^.RefType);
  945. end;
  946. { TRttiPool }
  947. function TRttiPool.GetTypes: specialize TArray<TRttiType>;
  948. begin
  949. if not Assigned(FTypesList) then
  950. Exit(Nil);
  951. {$ifdef FPC_HAS_FEATURE_THREADING}
  952. EnterCriticalsection(FLock);
  953. try
  954. {$endif}
  955. Result := Copy(FTypesList, 0, FTypeCount);
  956. {$ifdef FPC_HAS_FEATURE_THREADING}
  957. finally
  958. LeaveCriticalsection(FLock);
  959. end;
  960. {$endif}
  961. end;
  962. function TRttiPool.GetType(ATypeInfo: PTypeInfo): TRttiType;
  963. var
  964. obj: TRttiObject;
  965. begin
  966. if not Assigned(ATypeInfo) then
  967. Exit(Nil);
  968. {$ifdef FPC_HAS_FEATURE_THREADING}
  969. EnterCriticalsection(FLock);
  970. try
  971. {$endif}
  972. Result := Nil;
  973. obj := GetByHandle(ATypeInfo);
  974. if Assigned(obj) then
  975. Result := obj as TRttiType;
  976. if not Assigned(Result) then
  977. begin
  978. if FTypeCount = Length(FTypesList) then
  979. begin
  980. SetLength(FTypesList, FTypeCount * 2);
  981. end;
  982. case ATypeInfo^.Kind of
  983. tkClass : Result := TRttiInstanceType.Create(ATypeInfo);
  984. tkInterface: Result := TRttiRefCountedInterfaceType.Create(ATypeInfo);
  985. tkInterfaceRaw: Result := TRttiRawInterfaceType.Create(ATypeInfo);
  986. tkSString,
  987. tkLString,
  988. tkAString,
  989. tkUString,
  990. tkWString : Result := TRttiStringType.Create(ATypeInfo);
  991. tkFloat : Result := TRttiFloatType.Create(ATypeInfo);
  992. tkPointer : Result := TRttiPointerType.Create(ATypeInfo);
  993. tkProcVar : Result := TRttiProcedureType.Create(ATypeInfo);
  994. tkMethod : Result := TRttiMethodType.Create(ATypeInfo);
  995. else
  996. Result := TRttiType.Create(ATypeInfo);
  997. end;
  998. FTypesList[FTypeCount] := Result;
  999. FObjectMap.Add(ATypeInfo, Result);
  1000. Inc(FTypeCount);
  1001. end;
  1002. {$ifdef FPC_HAS_FEATURE_THREADING}
  1003. finally
  1004. LeaveCriticalsection(FLock);
  1005. end;
  1006. {$endif}
  1007. end;
  1008. function TRttiPool.GetByHandle(aHandle: Pointer): TRttiObject;
  1009. var
  1010. idx: LongInt;
  1011. begin
  1012. if not Assigned(aHandle) then
  1013. Exit(Nil);
  1014. {$ifdef FPC_HAS_FEATURE_THREADING}
  1015. EnterCriticalsection(FLock);
  1016. try
  1017. {$endif}
  1018. idx := FObjectMap.IndexOf(aHandle);
  1019. if idx < 0 then
  1020. Result := Nil
  1021. else
  1022. Result := FObjectMap.Data[idx];
  1023. {$ifdef FPC_HAS_FEATURE_THREADING}
  1024. finally
  1025. LeaveCriticalsection(FLock);
  1026. end;
  1027. {$endif}
  1028. end;
  1029. procedure TRttiPool.AddObject(aObject: TRttiObject);
  1030. var
  1031. idx: LongInt;
  1032. begin
  1033. if not Assigned(aObject) then
  1034. Exit;
  1035. if not Assigned(aObject.Handle) then
  1036. raise EArgumentException.Create(SErrRttiObjectNoHandle);
  1037. {$ifdef FPC_HAS_FEATURE_THREADING}
  1038. EnterCriticalsection(FLock);
  1039. try
  1040. {$endif}
  1041. idx := FObjectMap.IndexOf(aObject.Handle);
  1042. if idx < 0 then
  1043. FObjectMap.Add(aObject.Handle, aObject)
  1044. else if FObjectMap.Data[idx] <> aObject then
  1045. raise EInvalidOpException.CreateFmt(SErrRttiObjectAlreadyRegistered, [aObject.Handle]);
  1046. {$ifdef FPC_HAS_FEATURE_THREADING}
  1047. finally
  1048. LeaveCriticalsection(FLock);
  1049. end;
  1050. {$endif}
  1051. end;
  1052. constructor TRttiPool.Create;
  1053. begin
  1054. {$ifdef FPC_HAS_FEATURE_THREADING}
  1055. InitCriticalSection(FLock);
  1056. {$endif}
  1057. SetLength(FTypesList, 32);
  1058. FObjectMap := TRttiObjectMap.Create;
  1059. end;
  1060. destructor TRttiPool.Destroy;
  1061. var
  1062. i: LongInt;
  1063. begin
  1064. for i := 0 to FObjectMap.Count - 1 do
  1065. FObjectMap.Data[i].Free;
  1066. FObjectMap.Free;
  1067. {$ifdef FPC_HAS_FEATURE_THREADING}
  1068. DoneCriticalsection(FLock);
  1069. {$endif}
  1070. inherited Destroy;
  1071. end;
  1072. { TPoolToken }
  1073. constructor TPoolToken.Create;
  1074. begin
  1075. inherited Create;
  1076. if InterlockedIncrement(PoolRefCount)=1 then
  1077. GRttiPool := TRttiPool.Create;
  1078. end;
  1079. destructor TPoolToken.Destroy;
  1080. begin
  1081. if InterlockedDecrement(PoolRefCount)=0 then
  1082. GRttiPool.Free;
  1083. inherited;
  1084. end;
  1085. function TPoolToken.RttiPool: TRttiPool;
  1086. begin
  1087. result := GRttiPool;
  1088. end;
  1089. { TValueDataIntImpl }
  1090. procedure IntFinalize(APointer, ATypeInfo: Pointer);
  1091. external name 'FPC_FINALIZE';
  1092. procedure IntInitialize(APointer, ATypeInfo: Pointer);
  1093. external name 'FPC_INITIALIZE';
  1094. procedure IntAddRef(APointer, ATypeInfo: Pointer);
  1095. external name 'FPC_ADDREF';
  1096. function IntCopy(ASource, ADest, ATypeInfo: Pointer): SizeInt;
  1097. external name 'FPC_COPY';
  1098. constructor TValueDataIntImpl.CreateCopy(ACopyFromBuffer: Pointer; ALen: SizeInt; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  1099. begin
  1100. FTypeInfo := ATypeInfo;
  1101. FDataSize:=ALen;
  1102. if ALen>0 then
  1103. begin
  1104. Getmem(FBuffer,FDataSize);
  1105. if Assigned(ACopyFromBuffer) then
  1106. system.move(ACopyFromBuffer^,FBuffer^,FDataSize)
  1107. else
  1108. FillChar(FBuffer^, FDataSize, 0);
  1109. end;
  1110. FIsCopy := True;
  1111. FUseAddRef := AAddRef;
  1112. if AAddRef and (ALen > 0) then begin
  1113. if Assigned(ACopyFromBuffer) then
  1114. IntAddRef(FBuffer, FTypeInfo)
  1115. else
  1116. IntInitialize(FBuffer, FTypeInfo);
  1117. end;
  1118. end;
  1119. constructor TValueDataIntImpl.CreateRef(AData: Pointer; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  1120. begin
  1121. FTypeInfo := ATypeInfo;
  1122. FDataSize := SizeOf(Pointer);
  1123. if Assigned(AData) then
  1124. FBuffer := PPointer(AData)^
  1125. else
  1126. FBuffer := Nil;
  1127. FIsCopy := False;
  1128. FUseAddRef := AAddRef;
  1129. if AAddRef and Assigned(AData) then
  1130. IntAddRef(@FBuffer, FTypeInfo);
  1131. end;
  1132. destructor TValueDataIntImpl.Destroy;
  1133. begin
  1134. if Assigned(FBuffer) then begin
  1135. if FUseAddRef then
  1136. if FIsCopy then
  1137. IntFinalize(FBuffer, FTypeInfo)
  1138. else
  1139. IntFinalize(@FBuffer, FTypeInfo);
  1140. if FIsCopy then
  1141. Freemem(FBuffer);
  1142. end;
  1143. inherited Destroy;
  1144. end;
  1145. procedure TValueDataIntImpl.ExtractRawData(ABuffer: pointer);
  1146. begin
  1147. if FDataSize = 0 then
  1148. Exit;
  1149. if FIsCopy then
  1150. System.Move(FBuffer^, ABuffer^, FDataSize)
  1151. else
  1152. System.Move(FBuffer{!}, ABuffer^, FDataSize);
  1153. if FUseAddRef then
  1154. IntAddRef(ABuffer, FTypeInfo);
  1155. end;
  1156. procedure TValueDataIntImpl.ExtractRawDataNoCopy(ABuffer: pointer);
  1157. begin
  1158. if FDataSize = 0 then
  1159. Exit;
  1160. if FIsCopy then
  1161. system.move(FBuffer^, ABuffer^, FDataSize)
  1162. else
  1163. System.Move(FBuffer{!}, ABuffer^, FDataSize);
  1164. end;
  1165. function TValueDataIntImpl.GetDataSize: SizeInt;
  1166. begin
  1167. result := FDataSize;
  1168. end;
  1169. function TValueDataIntImpl.GetReferenceToRawData: pointer;
  1170. begin
  1171. if FIsCopy then
  1172. result := FBuffer
  1173. else
  1174. result := @FBuffer;
  1175. end;
  1176. { TRttiRefCountedInterfaceType }
  1177. function TRttiRefCountedInterfaceType.IntfData: PInterfaceData;
  1178. begin
  1179. Result := PInterfaceData(FTypeData);
  1180. end;
  1181. function TRttiRefCountedInterfaceType.MethodTable: PIntfMethodTable;
  1182. begin
  1183. Result := IntfData^.MethodTable;
  1184. end;
  1185. function TRttiRefCountedInterfaceType.GetIntfBaseType: TRttiInterfaceType;
  1186. var
  1187. context: TRttiContext;
  1188. begin
  1189. if not Assigned(IntfData^.Parent) then
  1190. Exit(Nil);
  1191. context := TRttiContext.Create;
  1192. try
  1193. Result := context.GetType(IntfData^.Parent^) as TRttiInterfaceType;
  1194. finally
  1195. context.Free;
  1196. end;
  1197. end;
  1198. function TRttiRefCountedInterfaceType.GetDeclaringUnitName: String;
  1199. begin
  1200. Result := IntfData^.UnitName;
  1201. end;
  1202. function TRttiRefCountedInterfaceType.GetGUID: TGUID;
  1203. begin
  1204. Result := IntfData^.GUID;
  1205. end;
  1206. function TRttiRefCountedInterfaceType.GetIntfFlags: TIntfFlags;
  1207. begin
  1208. Result := IntfData^.Flags;
  1209. end;
  1210. function TRttiRefCountedInterfaceType.GetIntfType: TInterfaceType;
  1211. begin
  1212. Result := itRefCounted;
  1213. end;
  1214. { TRttiRawInterfaceType }
  1215. function TRttiRawInterfaceType.IntfData: PInterfaceRawData;
  1216. begin
  1217. Result := PInterfaceRawData(FTypeData);
  1218. end;
  1219. function TRttiRawInterfaceType.MethodTable: PIntfMethodTable;
  1220. begin
  1221. { currently there is none! }
  1222. Result := Nil;
  1223. end;
  1224. function TRttiRawInterfaceType.GetIntfBaseType: TRttiInterfaceType;
  1225. var
  1226. context: TRttiContext;
  1227. begin
  1228. if not Assigned(IntfData^.Parent) then
  1229. Exit(Nil);
  1230. context := TRttiContext.Create;
  1231. try
  1232. Result := context.GetType(IntfData^.Parent^) as TRttiInterfaceType;
  1233. finally
  1234. context.Free;
  1235. end;
  1236. end;
  1237. function TRttiRawInterfaceType.GetDeclaringUnitName: String;
  1238. begin
  1239. Result := IntfData^.UnitName;
  1240. end;
  1241. function TRttiRawInterfaceType.GetGUID: TGUID;
  1242. begin
  1243. Result := IntfData^.IID;
  1244. end;
  1245. function TRttiRawInterfaceType.GetGUIDStr: String;
  1246. begin
  1247. Result := IntfData^.IIDStr;
  1248. end;
  1249. function TRttiRawInterfaceType.GetIntfFlags: TIntfFlags;
  1250. begin
  1251. Result := IntfData^.Flags;
  1252. end;
  1253. function TRttiRawInterfaceType.GetIntfType: TInterfaceType;
  1254. begin
  1255. Result := itRaw;
  1256. end;
  1257. { TRttiVmtMethodParameter }
  1258. function TRttiVmtMethodParameter.GetHandle: Pointer;
  1259. begin
  1260. Result := FVmtMethodParam;
  1261. end;
  1262. function TRttiVmtMethodParameter.GetName: String;
  1263. begin
  1264. Result := FVmtMethodParam^.Name;
  1265. end;
  1266. function TRttiVmtMethodParameter.GetFlags: TParamFlags;
  1267. begin
  1268. Result := FVmtMethodParam^.Flags;
  1269. end;
  1270. function TRttiVmtMethodParameter.GetParamType: TRttiType;
  1271. var
  1272. context: TRttiContext;
  1273. begin
  1274. if not Assigned(FVmtMethodParam^.ParamType) then
  1275. Exit(Nil);
  1276. context := TRttiContext.Create;
  1277. try
  1278. Result := context.GetType(FVmtMethodParam^.ParamType^);
  1279. finally
  1280. context.Free;
  1281. end;
  1282. end;
  1283. constructor TRttiVmtMethodParameter.Create(AVmtMethodParam: PVmtMethodParam);
  1284. begin
  1285. inherited Create;
  1286. FVmtMethodParam := AVmtMethodParam;
  1287. end;
  1288. { TRttiMethodTypeParameter }
  1289. function TRttiMethodTypeParameter.GetHandle: Pointer;
  1290. begin
  1291. Result := fHandle;
  1292. end;
  1293. function TRttiMethodTypeParameter.GetName: String;
  1294. begin
  1295. Result := fName;
  1296. end;
  1297. function TRttiMethodTypeParameter.GetFlags: TParamFlags;
  1298. begin
  1299. Result := fFlags;
  1300. end;
  1301. function TRttiMethodTypeParameter.GetParamType: TRttiType;
  1302. var
  1303. context: TRttiContext;
  1304. begin
  1305. context := TRttiContext.Create;
  1306. try
  1307. Result := context.GetType(FType);
  1308. finally
  1309. context.Free;
  1310. end;
  1311. end;
  1312. constructor TRttiMethodTypeParameter.Create(aHandle: Pointer; const aName: String; aFlags: TParamFlags; aType: PTypeInfo);
  1313. begin
  1314. fHandle := aHandle;
  1315. fName := aName;
  1316. fFlags := aFlags;
  1317. fType := aType;
  1318. end;
  1319. { TRttiIntfMethod }
  1320. function TRttiIntfMethod.GetHandle: Pointer;
  1321. begin
  1322. Result := FIntfMethodEntry;
  1323. end;
  1324. function TRttiIntfMethod.GetName: String;
  1325. begin
  1326. Result := FIntfMethodEntry^.Name;
  1327. end;
  1328. function TRttiIntfMethod.GetCallingConvention: TCallConv;
  1329. begin
  1330. Result := FIntfMethodEntry^.CC;
  1331. end;
  1332. function TRttiIntfMethod.GetCodeAddress: CodePointer;
  1333. begin
  1334. Result := Nil;
  1335. end;
  1336. function TRttiIntfMethod.GetDispatchKind: TDispatchKind;
  1337. begin
  1338. Result := dkInterface;
  1339. end;
  1340. function TRttiIntfMethod.GetHasExtendedInfo: Boolean;
  1341. begin
  1342. Result := True;
  1343. end;
  1344. function TRttiIntfMethod.GetIsClassMethod: Boolean;
  1345. begin
  1346. Result := False;
  1347. end;
  1348. function TRttiIntfMethod.GetIsConstructor: Boolean;
  1349. begin
  1350. Result := False;
  1351. end;
  1352. function TRttiIntfMethod.GetIsDestructor: Boolean;
  1353. begin
  1354. Result := False;
  1355. end;
  1356. function TRttiIntfMethod.GetIsStatic: Boolean;
  1357. begin
  1358. Result := False;
  1359. end;
  1360. function TRttiIntfMethod.GetMethodKind: TMethodKind;
  1361. begin
  1362. Result := FIntfMethodEntry^.Kind;
  1363. end;
  1364. function TRttiIntfMethod.GetReturnType: TRttiType;
  1365. var
  1366. context: TRttiContext;
  1367. begin
  1368. if not Assigned(FIntfMethodEntry^.ResultType) then
  1369. Exit(Nil);
  1370. context := TRttiContext.Create;
  1371. try
  1372. Result := context.GetType(FIntfMethodEntry^.ResultType^);
  1373. finally
  1374. context.Free;
  1375. end;
  1376. end;
  1377. function TRttiIntfMethod.GetVirtualIndex: SmallInt;
  1378. begin
  1379. Result := FIndex;
  1380. end;
  1381. constructor TRttiIntfMethod.Create(AParent: TRttiType; AIntfMethodEntry: PIntfMethodEntry; AIndex: SmallInt);
  1382. begin
  1383. inherited Create(AParent);
  1384. FIntfMethodEntry := AIntfMethodEntry;
  1385. FIndex := AIndex;
  1386. end;
  1387. function TRttiIntfMethod.GetParameters(aWithHidden: Boolean): specialize TArray<TRttiParameter>;
  1388. var
  1389. param: PVmtMethodParam;
  1390. total, visible: SizeInt;
  1391. context: TRttiContext;
  1392. obj: TRttiObject;
  1393. begin
  1394. if aWithHidden and (Length(FParamsAll) > 0) then
  1395. Exit(FParamsAll);
  1396. if not aWithHidden and (Length(FParams) > 0) then
  1397. Exit(FParams);
  1398. if FIntfMethodEntry^.ParamCount = 0 then
  1399. Exit(Nil);
  1400. SetLength(FParams, FIntfMethodEntry^.ParamCount);
  1401. SetLength(FParamsAll, FIntfMethodEntry^.ParamCount);
  1402. context := TRttiContext.Create;
  1403. try
  1404. total := 0;
  1405. visible := 0;
  1406. param := FIntfMethodEntry^.Param[0];
  1407. while total < FIntfMethodEntry^.ParamCount do begin
  1408. obj := context.GetByHandle(param);
  1409. if Assigned(obj) then
  1410. FParamsAll[total] := obj as TRttiVmtMethodParameter
  1411. else begin
  1412. FParamsAll[total] := TRttiVmtMethodParameter.Create(param);
  1413. context.AddObject(FParamsAll[total]);
  1414. end;
  1415. if not (pfHidden in param^.Flags) then begin
  1416. FParams[visible] := FParamsAll[total];
  1417. Inc(visible);
  1418. end;
  1419. param := param^.Next;
  1420. Inc(total);
  1421. end;
  1422. if visible <> total then
  1423. SetLength(FParams, visible);
  1424. finally
  1425. context.Free;
  1426. end;
  1427. if aWithHidden then
  1428. Result := FParamsAll
  1429. else
  1430. Result := FParams;
  1431. end;
  1432. { TRttiFloatType }
  1433. function TRttiFloatType.GetFloatType: TFloatType;
  1434. begin
  1435. result := FTypeData^.FloatType;
  1436. end;
  1437. { TValue }
  1438. class function TValue.Empty: TValue;
  1439. begin
  1440. result.FData.FTypeInfo := nil;
  1441. {$if SizeOf(TMethod) > SizeOf(QWord)}
  1442. Result.FData.FAsMethod.Code := Nil;
  1443. Result.FData.FAsMethod.Data := Nil;
  1444. {$else}
  1445. Result.FData.FAsUInt64 := 0;
  1446. {$endif}
  1447. end;
  1448. class procedure TValue.Make(ABuffer: pointer; ATypeInfo: PTypeInfo; out result: TValue);
  1449. type
  1450. PBoolean16 = ^Boolean16;
  1451. PBoolean32 = ^Boolean32;
  1452. PBoolean64 = ^Boolean64;
  1453. PByteBool = ^ByteBool;
  1454. PQWordBool = ^QWordBool;
  1455. PMethod = ^TMethod;
  1456. var
  1457. td: PTypeData;
  1458. size: SizeInt;
  1459. begin
  1460. result.FData.FTypeInfo:=ATypeInfo;
  1461. { resets the whole variant part; FValueData is already Nil }
  1462. {$if SizeOf(TMethod) > SizeOf(QWord)}
  1463. Result.FData.FAsMethod.Code := Nil;
  1464. Result.FData.FAsMethod.Data := Nil;
  1465. {$else}
  1466. Result.FData.FAsUInt64 := 0;
  1467. {$endif}
  1468. if not Assigned(ATypeInfo) then
  1469. Exit;
  1470. { first handle those types that need a TValueData implementation }
  1471. case ATypeInfo^.Kind of
  1472. tkSString : begin
  1473. td := GetTypeData(ATypeInfo);
  1474. result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, td^.MaxLength + 1, ATypeInfo, True);
  1475. end;
  1476. tkWString,
  1477. tkUString,
  1478. tkAString : result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  1479. tkDynArray : result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  1480. tkArray : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, Result.TypeData^.ArrayData.Size, ATypeInfo, False);
  1481. tkObject,
  1482. tkRecord : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, Result.TypeData^.RecSize, ATypeInfo, False);
  1483. tkInterface: result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  1484. end;
  1485. if not Assigned(ABuffer) then
  1486. Exit;
  1487. { now handle those that are happy with the variant part of FData }
  1488. case ATypeInfo^.Kind of
  1489. tkSString,
  1490. tkWString,
  1491. tkUString,
  1492. tkAString,
  1493. tkDynArray,
  1494. tkArray,
  1495. tkObject,
  1496. tkRecord,
  1497. tkInterface:
  1498. { ignore }
  1499. ;
  1500. tkClass : result.FData.FAsObject := PPointer(ABuffer)^;
  1501. tkClassRef : result.FData.FAsClass := PClass(ABuffer)^;
  1502. tkInterfaceRaw : result.FData.FAsPointer := PPointer(ABuffer)^;
  1503. tkInt64 : result.FData.FAsSInt64 := PInt64(ABuffer)^;
  1504. tkQWord : result.FData.FAsUInt64 := PQWord(ABuffer)^;
  1505. tkProcVar : result.FData.FAsMethod.Code := PCodePointer(ABuffer)^;
  1506. tkMethod : result.FData.FAsMethod := PMethod(ABuffer)^;
  1507. tkPointer : result.FData.FAsPointer := PPointer(ABuffer)^;
  1508. tkSet : begin
  1509. td := GetTypeData(ATypeInfo);
  1510. case td^.OrdType of
  1511. otUByte: begin
  1512. { this can either really be 1 Byte or a set > 32-bit, so
  1513. check the underlying type }
  1514. if not (td^.CompType^.Kind in [tkInteger,tkEnumeration]) then
  1515. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  1516. case td^.SetSize of
  1517. 0, 1:
  1518. Result.FData.FAsUByte := PByte(ABuffer)^;
  1519. { these two cases shouldn't happen, but better safe than sorry... }
  1520. 2:
  1521. Result.FData.FAsUWord := PWord(ABuffer)^;
  1522. 3, 4:
  1523. Result.FData.FAsULong := PLongWord(ABuffer)^;
  1524. { maybe we should also allow storage as otUQWord? }
  1525. 5..8:
  1526. Result.FData.FAsUInt64 := PQWord(ABuffer)^;
  1527. else
  1528. Result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, td^.SetSize, ATypeInfo, False);
  1529. end;
  1530. end;
  1531. otUWord:
  1532. Result.FData.FAsUWord := PWord(ABuffer)^;
  1533. otULong:
  1534. Result.FData.FAsULong := PLongWord(ABuffer)^;
  1535. else
  1536. { ehm... Panic? }
  1537. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  1538. end;
  1539. end;
  1540. tkEnumeration,
  1541. tkInteger : begin
  1542. case GetTypeData(ATypeInfo)^.OrdType of
  1543. otSByte: result.FData.FAsSByte := PShortInt(ABuffer)^;
  1544. otUByte: result.FData.FAsUByte := PByte(ABuffer)^;
  1545. otSWord: result.FData.FAsSWord := PSmallInt(ABuffer)^;
  1546. otUWord: result.FData.FAsUWord := PWord(ABuffer)^;
  1547. otSLong: result.FData.FAsSLong := PLongInt(ABuffer)^;
  1548. otULong: result.FData.FAsULong := PLongWord(ABuffer)^;
  1549. end;
  1550. end;
  1551. tkBool : begin
  1552. case GetTypeData(ATypeInfo)^.OrdType of
  1553. otUByte: result.FData.FAsSByte := ShortInt(System.PBoolean(ABuffer)^);
  1554. otUWord: result.FData.FAsUWord := Byte(PBoolean16(ABuffer)^);
  1555. otULong: result.FData.FAsULong := SmallInt(PBoolean32(ABuffer)^);
  1556. otUQWord: result.FData.FAsUInt64 := QWord(PBoolean64(ABuffer)^);
  1557. otSByte: result.FData.FAsSByte := Word(PByteBool(ABuffer)^);
  1558. otSWord: result.FData.FAsSWord := LongInt(PWordBool(ABuffer)^);
  1559. otSLong: result.FData.FAsSLong := LongWord(PLongBool(ABuffer)^);
  1560. otSQWord: result.FData.FAsSInt64 := Int64(PQWordBool(ABuffer)^);
  1561. end;
  1562. end;
  1563. tkFloat : begin
  1564. case GetTypeData(ATypeInfo)^.FloatType of
  1565. ftCurr : result.FData.FAsCurr := PCurrency(ABuffer)^;
  1566. ftSingle : result.FData.FAsSingle := PSingle(ABuffer)^;
  1567. ftDouble : result.FData.FAsDouble := PDouble(ABuffer)^;
  1568. ftExtended: result.FData.FAsExtended := PExtended(ABuffer)^;
  1569. ftComp : result.FData.FAsComp := PComp(ABuffer)^;
  1570. end;
  1571. end;
  1572. else
  1573. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  1574. end;
  1575. end;
  1576. class procedure TValue.MakeOpenArray(AArray: Pointer; ALength: SizeInt; ATypeInfo: PTypeInfo; out Result: TValue);
  1577. var
  1578. el: TValue;
  1579. begin
  1580. Result.FData.FTypeInfo := ATypeInfo;
  1581. { resets the whole variant part; FValueData is already Nil }
  1582. {$if SizeOf(TMethod) > SizeOf(QWord)}
  1583. Result.FData.FAsMethod.Code := Nil;
  1584. Result.FData.FAsMethod.Data := Nil;
  1585. {$else}
  1586. Result.FData.FAsUInt64 := 0;
  1587. {$endif}
  1588. if not Assigned(ATypeInfo) then
  1589. Exit;
  1590. if ATypeInfo^.Kind <> tkArray then
  1591. Exit;
  1592. if not Assigned(AArray) then
  1593. Exit;
  1594. if ALength < 0 then
  1595. Exit;
  1596. Result.FData.FValueData := TValueDataIntImpl.CreateRef(@AArray, ATypeInfo, False);
  1597. Result.FData.FArrLength := ALength;
  1598. Make(Nil, Result.TypeData^.ArrayData.ElType, el);
  1599. Result.FData.FElSize := el.DataSize;
  1600. end;
  1601. {$ifndef NoGenericMethods}
  1602. generic class function TValue.From<T>(constref aValue: T): TValue;
  1603. begin
  1604. TValue.Make(@aValue, System.TypeInfo(T), Result);
  1605. end;
  1606. generic class function TValue.FromOpenArray<T>(constref aValue: array of T): TValue;
  1607. var
  1608. arrdata: Pointer;
  1609. begin
  1610. if Length(aValue) > 0 then
  1611. arrdata := @aValue[0]
  1612. else
  1613. arrdata := Nil;
  1614. TValue.MakeOpenArray(arrdata, Length(aValue), System.TypeInfo(aValue), Result);
  1615. end;
  1616. {$endif}
  1617. function TValue.GetTypeDataProp: PTypeData;
  1618. begin
  1619. result := GetTypeData(FData.FTypeInfo);
  1620. end;
  1621. function TValue.GetDataSize: SizeInt;
  1622. begin
  1623. if Assigned(FData.FValueData) and (Kind <> tkSString) then
  1624. Result := FData.FValueData.GetDataSize
  1625. else begin
  1626. Result := 0;
  1627. case Kind of
  1628. tkEnumeration,
  1629. tkBool,
  1630. tkInt64,
  1631. tkQWord,
  1632. tkInteger:
  1633. case TypeData^.OrdType of
  1634. otSByte,
  1635. otUByte:
  1636. Result := SizeOf(Byte);
  1637. otSWord,
  1638. otUWord:
  1639. Result := SizeOf(Word);
  1640. otSLong,
  1641. otULong:
  1642. Result := SizeOf(LongWord);
  1643. otSQWord,
  1644. otUQWord:
  1645. Result := SizeOf(QWord);
  1646. end;
  1647. tkChar:
  1648. Result := SizeOf(AnsiChar);
  1649. tkFloat:
  1650. case TypeData^.FloatType of
  1651. ftSingle:
  1652. Result := SizeOf(Single);
  1653. ftDouble:
  1654. Result := SizeOf(Double);
  1655. ftExtended:
  1656. Result := SizeOf(Extended);
  1657. ftComp:
  1658. Result := SizeOf(Comp);
  1659. ftCurr:
  1660. Result := SizeOf(Currency);
  1661. end;
  1662. tkSet:
  1663. Result := TypeData^.SetSize;
  1664. tkMethod:
  1665. Result := SizeOf(TMethod);
  1666. tkSString:
  1667. { ShortString can hold max. 254 characters as [0] is Length and [255] is #0 }
  1668. Result := SizeOf(ShortString) - 2;
  1669. tkVariant:
  1670. Result := SizeOf(Variant);
  1671. tkProcVar:
  1672. Result := SizeOf(CodePointer);
  1673. tkWChar:
  1674. Result := SizeOf(WideChar);
  1675. tkUChar:
  1676. Result := SizeOf(UnicodeChar);
  1677. tkFile:
  1678. { ToDo }
  1679. Result := SizeOf(TTextRec);
  1680. tkAString,
  1681. tkWString,
  1682. tkUString,
  1683. tkInterface,
  1684. tkDynArray,
  1685. tkClass,
  1686. tkHelper,
  1687. tkClassRef,
  1688. tkInterfaceRaw,
  1689. tkPointer:
  1690. Result := SizeOf(Pointer);
  1691. tkObject,
  1692. tkRecord:
  1693. Result := TypeData^.RecSize;
  1694. tkArray:
  1695. Result := TypeData^.ArrayData.Size;
  1696. tkUnknown,
  1697. tkLString:
  1698. Assert(False);
  1699. end;
  1700. end;
  1701. end;
  1702. function TValue.GetTypeInfo: PTypeInfo;
  1703. begin
  1704. result := FData.FTypeInfo;
  1705. end;
  1706. function TValue.GetTypeKind: TTypeKind;
  1707. begin
  1708. if not Assigned(FData.FTypeInfo) then
  1709. Result := tkUnknown
  1710. else
  1711. result := FData.FTypeInfo^.Kind;
  1712. end;
  1713. function TValue.GetIsEmpty: boolean;
  1714. begin
  1715. result := (FData.FTypeInfo=nil) or
  1716. ((Kind in [tkSString, tkObject, tkRecord, tkArray]) and not Assigned(FData.FValueData)) or
  1717. ((Kind in [tkClass, tkClassRef, tkInterfaceRaw]) and not Assigned(FData.FAsPointer));
  1718. end;
  1719. function TValue.IsArray: boolean;
  1720. begin
  1721. result := kind in [tkArray, tkDynArray];
  1722. end;
  1723. function TValue.IsOpenArray: Boolean;
  1724. var
  1725. td: PTypeData;
  1726. begin
  1727. td := TypeData;
  1728. Result := (Kind = tkArray) and (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0)
  1729. end;
  1730. function TValue.AsString: string;
  1731. begin
  1732. if System.GetTypeKind(String) = tkUString then
  1733. Result := String(AsUnicodeString)
  1734. else
  1735. Result := String(AsAnsiString);
  1736. end;
  1737. function TValue.AsUnicodeString: UnicodeString;
  1738. begin
  1739. if (Kind in [tkSString, tkAString, tkUString, tkWString]) and not Assigned(FData.FValueData) then
  1740. Result := ''
  1741. else
  1742. case Kind of
  1743. tkSString:
  1744. Result := UnicodeString(PShortString(FData.FValueData.GetReferenceToRawData)^);
  1745. tkAString:
  1746. Result := UnicodeString(PAnsiString(FData.FValueData.GetReferenceToRawData)^);
  1747. tkWString:
  1748. Result := UnicodeString(PWideString(FData.FValueData.GetReferenceToRawData)^);
  1749. tkUString:
  1750. Result := UnicodeString(PUnicodeString(FData.FValueData.GetReferenceToRawData)^);
  1751. else
  1752. raise EInvalidCast.Create(SErrInvalidTypecast);
  1753. end;
  1754. end;
  1755. function TValue.AsAnsiString: AnsiString;
  1756. begin
  1757. if (Kind in [tkSString, tkAString, tkUString, tkWString]) and not Assigned(FData.FValueData) then
  1758. Result := ''
  1759. else
  1760. case Kind of
  1761. tkSString:
  1762. Result := AnsiString(PShortString(FData.FValueData.GetReferenceToRawData)^);
  1763. tkAString:
  1764. Result := AnsiString(PAnsiString(FData.FValueData.GetReferenceToRawData)^);
  1765. tkWString:
  1766. Result := AnsiString(PWideString(FData.FValueData.GetReferenceToRawData)^);
  1767. tkUString:
  1768. Result := AnsiString(PUnicodeString(FData.FValueData.GetReferenceToRawData)^);
  1769. else
  1770. raise EInvalidCast.Create(SErrInvalidTypecast);
  1771. end;
  1772. end;
  1773. function TValue.AsExtended: Extended;
  1774. begin
  1775. if Kind = tkFloat then
  1776. begin
  1777. case TypeData^.FloatType of
  1778. ftSingle : result := FData.FAsSingle;
  1779. ftDouble : result := FData.FAsDouble;
  1780. ftExtended : result := FData.FAsExtended;
  1781. ftCurr : result := FData.FAsCurr;
  1782. ftComp : result := FData.FAsComp;
  1783. else
  1784. raise EInvalidCast.Create(SErrInvalidTypecast);
  1785. end;
  1786. end
  1787. else
  1788. raise EInvalidCast.Create(SErrInvalidTypecast);
  1789. end;
  1790. function TValue.AsObject: TObject;
  1791. begin
  1792. if IsObject or (IsClass and not Assigned(FData.FAsObject)) then
  1793. result := TObject(FData.FAsObject)
  1794. else
  1795. raise EInvalidCast.Create(SErrInvalidTypecast);
  1796. end;
  1797. function TValue.IsObject: boolean;
  1798. begin
  1799. result := (Kind = tkClass) or ((Kind = tkUnknown) and not Assigned(FData.FAsObject));
  1800. end;
  1801. function TValue.IsClass: boolean;
  1802. begin
  1803. result := (Kind = tkClassRef) or ((Kind in [tkClass,tkUnknown]) and not Assigned(FData.FAsObject));
  1804. end;
  1805. function TValue.AsClass: TClass;
  1806. begin
  1807. if IsClass then
  1808. result := FData.FAsClass
  1809. else
  1810. raise EInvalidCast.Create(SErrInvalidTypecast);
  1811. end;
  1812. function TValue.IsOrdinal: boolean;
  1813. begin
  1814. result := (Kind in [tkInteger, tkInt64, tkQWord, tkBool]) or
  1815. ((Kind in [tkClass, tkClassRef, tkInterfaceRaw, tkUnknown]) and not Assigned(FData.FAsPointer));
  1816. end;
  1817. function TValue.AsBoolean: boolean;
  1818. begin
  1819. if (Kind = tkBool) then
  1820. case TypeData^.OrdType of
  1821. otSByte: Result := ByteBool(FData.FAsSByte);
  1822. otUByte: Result := Boolean(FData.FAsUByte);
  1823. otSWord: Result := WordBool(FData.FAsSWord);
  1824. otUWord: Result := Boolean16(FData.FAsUWord);
  1825. otSLong: Result := LongBool(FData.FAsSLong);
  1826. otULong: Result := Boolean32(FData.FAsULong);
  1827. otSQWord: Result := QWordBool(FData.FAsSInt64);
  1828. otUQWord: Result := Boolean64(FData.FAsUInt64);
  1829. end
  1830. else
  1831. raise EInvalidCast.Create(SErrInvalidTypecast);
  1832. end;
  1833. function TValue.AsOrdinal: Int64;
  1834. begin
  1835. if IsOrdinal then
  1836. if Kind in [tkClass, tkClassRef, tkInterfaceRaw, tkUnknown] then
  1837. Result := 0
  1838. else
  1839. case TypeData^.OrdType of
  1840. otSByte: Result := FData.FAsSByte;
  1841. otUByte: Result := FData.FAsUByte;
  1842. otSWord: Result := FData.FAsSWord;
  1843. otUWord: Result := FData.FAsUWord;
  1844. otSLong: Result := FData.FAsSLong;
  1845. otULong: Result := FData.FAsULong;
  1846. otSQWord: Result := FData.FAsSInt64;
  1847. otUQWord: Result := FData.FAsUInt64;
  1848. end
  1849. else
  1850. raise EInvalidCast.Create(SErrInvalidTypecast);
  1851. end;
  1852. function TValue.AsCurrency: Currency;
  1853. begin
  1854. if (Kind = tkFloat) and (TypeData^.FloatType=ftCurr) then
  1855. result := FData.FAsCurr
  1856. else
  1857. raise EInvalidCast.Create(SErrInvalidTypecast);
  1858. end;
  1859. function TValue.AsInteger: Integer;
  1860. begin
  1861. if Kind in [tkInteger, tkInt64, tkQWord] then
  1862. case TypeData^.OrdType of
  1863. otSByte: Result := FData.FAsSByte;
  1864. otUByte: Result := FData.FAsUByte;
  1865. otSWord: Result := FData.FAsSWord;
  1866. otUWord: Result := FData.FAsUWord;
  1867. otSLong: Result := FData.FAsSLong;
  1868. otULong: Result := FData.FAsULong;
  1869. otSQWord: Result := FData.FAsSInt64;
  1870. otUQWord: Result := FData.FAsUInt64;
  1871. end
  1872. else
  1873. raise EInvalidCast.Create(SErrInvalidTypecast);
  1874. end;
  1875. function TValue.AsInt64: Int64;
  1876. begin
  1877. if Kind in [tkInteger, tkInt64, tkQWord] then
  1878. case TypeData^.OrdType of
  1879. otSByte: Result := FData.FAsSByte;
  1880. otUByte: Result := FData.FAsUByte;
  1881. otSWord: Result := FData.FAsSWord;
  1882. otUWord: Result := FData.FAsUWord;
  1883. otSLong: Result := FData.FAsSLong;
  1884. otULong: Result := FData.FAsULong;
  1885. otSQWord: Result := FData.FAsSInt64;
  1886. otUQWord: Result := FData.FAsUInt64;
  1887. end
  1888. else if (Kind = tkFloat) and (TypeData^.FloatType = ftComp) then
  1889. Result := Int64(FData.FAsComp)
  1890. else
  1891. raise EInvalidCast.Create(SErrInvalidTypecast);
  1892. end;
  1893. function TValue.AsUInt64: QWord;
  1894. begin
  1895. if Kind in [tkInteger, tkInt64, tkQWord] then
  1896. case TypeData^.OrdType of
  1897. otSByte: Result := FData.FAsSByte;
  1898. otUByte: Result := FData.FAsUByte;
  1899. otSWord: Result := FData.FAsSWord;
  1900. otUWord: Result := FData.FAsUWord;
  1901. otSLong: Result := FData.FAsSLong;
  1902. otULong: Result := FData.FAsULong;
  1903. otSQWord: Result := FData.FAsSInt64;
  1904. otUQWord: Result := FData.FAsUInt64;
  1905. end
  1906. else if (Kind = tkFloat) and (TypeData^.FloatType = ftComp) then
  1907. Result := QWord(FData.FAsComp)
  1908. else
  1909. raise EInvalidCast.Create(SErrInvalidTypecast);
  1910. end;
  1911. function TValue.AsInterface: IInterface;
  1912. begin
  1913. if Kind = tkInterface then
  1914. Result := PInterface(FData.FValueData.GetReferenceToRawData)^
  1915. else if (Kind in [tkClass, tkClassRef, tkUnknown]) and not Assigned(FData.FAsPointer) then
  1916. Result := Nil
  1917. else
  1918. raise EInvalidCast.Create(SErrInvalidTypecast);
  1919. end;
  1920. function TValue.ToString: String;
  1921. begin
  1922. case Kind of
  1923. tkWString,
  1924. tkUString : result := AsUnicodeString;
  1925. tkSString,
  1926. tkAString : result := AsAnsiString;
  1927. tkInteger : result := IntToStr(AsInteger);
  1928. tkQWord : result := IntToStr(AsUInt64);
  1929. tkInt64 : result := IntToStr(AsInt64);
  1930. tkBool : result := BoolToStr(AsBoolean, True);
  1931. else
  1932. result := '';
  1933. end;
  1934. end;
  1935. function TValue.GetArrayLength: SizeInt;
  1936. var
  1937. td: PTypeData;
  1938. begin
  1939. if not IsArray then
  1940. raise EInvalidCast.Create(SErrInvalidTypecast);
  1941. if Kind = tkDynArray then
  1942. Result := DynArraySize(PPointer(FData.FValueData.GetReferenceToRawData)^)
  1943. else begin
  1944. td := TypeData;
  1945. if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then
  1946. Result := FData.FArrLength
  1947. else
  1948. Result := td^.ArrayData.ElCount;
  1949. end;
  1950. end;
  1951. function TValue.GetArrayElement(AIndex: SizeInt): TValue;
  1952. var
  1953. data: Pointer;
  1954. eltype: PTypeInfo;
  1955. elsize: SizeInt;
  1956. td: PTypeData;
  1957. begin
  1958. if not IsArray then
  1959. raise EInvalidCast.Create(SErrInvalidTypecast);
  1960. if Kind = tkDynArray then begin
  1961. data := DynArrayIndex(PPointer(FData.FValueData.GetReferenceToRawData)^, [AIndex], FData.FTypeInfo);
  1962. eltype := TypeData^.elType2;
  1963. end else begin
  1964. td := TypeData;
  1965. eltype := td^.ArrayData.ElType;
  1966. { open array? }
  1967. if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then begin
  1968. data := PPointer(FData.FValueData.GetReferenceToRawData)^;
  1969. elsize := FData.FElSize
  1970. end else begin
  1971. data := FData.FValueData.GetReferenceToRawData;
  1972. elsize := td^.ArrayData.Size div td^.ArrayData.ElCount;
  1973. end;
  1974. data := PByte(data) + AIndex * elsize;
  1975. end;
  1976. { MakeWithoutCopy? }
  1977. Make(data, eltype, Result);
  1978. end;
  1979. procedure TValue.SetArrayElement(AIndex: SizeInt; constref AValue: TValue);
  1980. var
  1981. data: Pointer;
  1982. eltype: PTypeInfo;
  1983. elsize: SizeInt;
  1984. td, tdv: PTypeData;
  1985. begin
  1986. if not IsArray then
  1987. raise EInvalidCast.Create(SErrInvalidTypecast);
  1988. if Kind = tkDynArray then begin
  1989. data := DynArrayIndex(PPointer(FData.FValueData.GetReferenceToRawData)^, [AIndex], FData.FTypeInfo);
  1990. eltype := TypeData^.elType2;
  1991. end else begin
  1992. td := TypeData;
  1993. eltype := td^.ArrayData.ElType;
  1994. { open array? }
  1995. if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then begin
  1996. data := PPointer(FData.FValueData.GetReferenceToRawData)^;
  1997. elsize := FData.FElSize
  1998. end else begin
  1999. data := FData.FValueData.GetReferenceToRawData;
  2000. elsize := td^.ArrayData.Size div td^.ArrayData.ElCount;
  2001. end;
  2002. data := PByte(data) + AIndex * elsize;
  2003. end;
  2004. { maybe we'll later on allow some typecasts, but for now be restrictive }
  2005. if eltype^.Kind <> AValue.Kind then
  2006. raise EInvalidCast.Create(SErrInvalidTypecast);
  2007. td := GetTypeData(eltype);
  2008. tdv := AValue.TypeData;
  2009. if ((eltype^.Kind in [tkInteger, tkBool, tkEnumeration, tkSet]) and (td^.OrdType <> tdv^.OrdType)) or
  2010. ((eltype^.Kind = tkFloat) and (td^.FloatType <> tdv^.FloatType)) then
  2011. raise EInvalidCast.Create(SErrInvalidTypecast);
  2012. if Assigned(AValue.FData.FValueData) and (eltype^.Kind <> tkSString) then
  2013. IntCopy(AValue.FData.FValueData.GetReferenceToRawData, data, eltype)
  2014. else
  2015. Move(AValue.GetReferenceToRawData^, data^, AValue.DataSize);
  2016. end;
  2017. function TValue.IsType(ATypeInfo: PTypeInfo): boolean;
  2018. begin
  2019. result := ATypeInfo = TypeInfo;
  2020. end;
  2021. function TValue.TryAsOrdinal(out AResult: int64): boolean;
  2022. begin
  2023. result := IsOrdinal;
  2024. if result then
  2025. AResult := AsOrdinal;
  2026. end;
  2027. function TValue.GetReferenceToRawData: Pointer;
  2028. begin
  2029. if not Assigned(FData.FTypeInfo) then
  2030. Result := Nil
  2031. else if Assigned(FData.FValueData) then
  2032. Result := FData.FValueData.GetReferenceToRawData
  2033. else begin
  2034. Result := Nil;
  2035. case Kind of
  2036. tkInteger,
  2037. tkEnumeration,
  2038. tkInt64,
  2039. tkQWord,
  2040. tkBool:
  2041. case TypeData^.OrdType of
  2042. otSByte:
  2043. Result := @FData.FAsSByte;
  2044. otUByte:
  2045. Result := @FData.FAsUByte;
  2046. otSWord:
  2047. Result := @FData.FAsSWord;
  2048. otUWord:
  2049. Result := @FData.FAsUWord;
  2050. otSLong:
  2051. Result := @FData.FAsSLong;
  2052. otULong:
  2053. Result := @FData.FAsULong;
  2054. otSQWord:
  2055. Result := @FData.FAsSInt64;
  2056. otUQWord:
  2057. Result := @FData.FAsUInt64;
  2058. end;
  2059. tkSet: begin
  2060. case TypeData^.OrdType of
  2061. otUByte: begin
  2062. case TypeData^.SetSize of
  2063. 1:
  2064. Result := @FData.FAsUByte;
  2065. 2:
  2066. Result := @FData.FAsUWord;
  2067. 3, 4:
  2068. Result := @FData.FAsULong;
  2069. 5..8:
  2070. Result := @FData.FAsUInt64;
  2071. else
  2072. { this should have gone through FAsValueData :/ }
  2073. Result := Nil;
  2074. end;
  2075. end;
  2076. otUWord:
  2077. Result := @FData.FAsUWord;
  2078. otULong:
  2079. Result := @FData.FAsULong;
  2080. else
  2081. Result := Nil;
  2082. end;
  2083. end;
  2084. tkChar:
  2085. Result := @FData.FAsUByte;
  2086. tkFloat:
  2087. case TypeData^.FloatType of
  2088. ftSingle:
  2089. Result := @FData.FAsSingle;
  2090. ftDouble:
  2091. Result := @FData.FAsDouble;
  2092. ftExtended:
  2093. Result := @FData.FAsExtended;
  2094. ftComp:
  2095. Result := @FData.FAsComp;
  2096. ftCurr:
  2097. Result := @FData.FAsCurr;
  2098. end;
  2099. tkMethod:
  2100. Result := @FData.FAsMethod;
  2101. tkClass:
  2102. Result := @FData.FAsObject;
  2103. tkWChar:
  2104. Result := @FData.FAsUWord;
  2105. tkInterfaceRaw:
  2106. Result := @FData.FAsPointer;
  2107. tkProcVar:
  2108. Result := @FData.FAsMethod.Code;
  2109. tkUChar:
  2110. Result := @FData.FAsUWord;
  2111. tkFile:
  2112. Result := @FData.FAsPointer;
  2113. tkClassRef:
  2114. Result := @FData.FAsClass;
  2115. tkPointer:
  2116. Result := @FData.FAsPointer;
  2117. tkVariant,
  2118. tkDynArray,
  2119. tkArray,
  2120. tkObject,
  2121. tkRecord,
  2122. tkInterface,
  2123. tkSString,
  2124. tkLString,
  2125. tkAString,
  2126. tkUString,
  2127. tkWString:
  2128. Assert(false, 'Managed/complex type not handled through IValueData');
  2129. end;
  2130. end;
  2131. end;
  2132. procedure TValue.ExtractRawData(ABuffer: Pointer);
  2133. begin
  2134. if Assigned(FData.FValueData) then
  2135. FData.FValueData.ExtractRawData(ABuffer)
  2136. else if Assigned(FData.FTypeInfo) then
  2137. Move((@FData.FAsPointer)^, ABuffer^, DataSize);
  2138. end;
  2139. procedure TValue.ExtractRawDataNoCopy(ABuffer: Pointer);
  2140. begin
  2141. if Assigned(FData.FValueData) then
  2142. FData.FValueData.ExtractRawDataNoCopy(ABuffer)
  2143. else if Assigned(FData.FTypeInfo) then
  2144. Move((@FData.FAsPointer)^, ABuffer^, DataSize);
  2145. end;
  2146. class operator TValue.:=(const AValue: String): TValue;
  2147. begin
  2148. Make(@AValue, System.TypeInfo(AValue), Result);
  2149. end;
  2150. class operator TValue.:=(AValue: LongInt): TValue;
  2151. begin
  2152. Make(@AValue, System.TypeInfo(AValue), Result);
  2153. end;
  2154. class operator TValue.:=(AValue: Single): TValue;
  2155. begin
  2156. Make(@AValue, System.TypeInfo(AValue), Result);
  2157. end;
  2158. class operator TValue.:=(AValue: Double): TValue;
  2159. begin
  2160. Make(@AValue, System.TypeInfo(AValue), Result);
  2161. end;
  2162. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2163. class operator TValue.:=(AValue: Extended): TValue;
  2164. begin
  2165. Make(@AValue, System.TypeInfo(AValue), Result);
  2166. end;
  2167. {$endif}
  2168. class operator TValue.:=(AValue: Currency): TValue;
  2169. begin
  2170. Make(@AValue, System.TypeInfo(AValue), Result);
  2171. end;
  2172. class operator TValue.:=(AValue: Int64): TValue;
  2173. begin
  2174. Make(@AValue, System.TypeInfo(AValue), Result);
  2175. end;
  2176. class operator TValue.:=(AValue: QWord): TValue;
  2177. begin
  2178. Make(@AValue, System.TypeInfo(AValue), Result);
  2179. end;
  2180. class operator TValue.:=(AValue: TObject): TValue;
  2181. begin
  2182. Make(@AValue, System.TypeInfo(AValue), Result);
  2183. end;
  2184. class operator TValue.:=(AValue: TClass): TValue;
  2185. begin
  2186. Make(@AValue, System.TypeInfo(AValue), Result);
  2187. end;
  2188. class operator TValue.:=(AValue: Boolean): TValue;
  2189. begin
  2190. Make(@AValue, System.TypeInfo(AValue), Result);
  2191. end;
  2192. { TRttiParameter }
  2193. function TRttiParameter.ToString: String;
  2194. var
  2195. f: TParamFlags;
  2196. n: String;
  2197. t: TRttiType;
  2198. begin
  2199. if FString = '' then begin
  2200. f := Flags;
  2201. if pfVar in f then
  2202. FString := 'var'
  2203. else if pfConst in f then
  2204. FString := 'const'
  2205. else if pfOut in f then
  2206. FString := 'out'
  2207. else if pfConstRef in f then
  2208. FString := 'constref';
  2209. if FString <> '' then
  2210. FString := FString + ' ';
  2211. n := Name;
  2212. if n = '' then
  2213. n := '<unknown>';
  2214. FString := FString + n;
  2215. t := ParamType;
  2216. if Assigned(t) then begin
  2217. FString := FString + ': ';
  2218. if pfArray in flags then
  2219. FString := 'array of ';
  2220. FString := FString + t.Name;
  2221. end;
  2222. end;
  2223. Result := FString;
  2224. end;
  2225. { TMethodImplementation }
  2226. function TMethodImplementation.GetCodeAddress: CodePointer;
  2227. begin
  2228. Result := fLowLevelCallback.CodeAddress;
  2229. end;
  2230. procedure TMethodImplementation.InitArgs;
  2231. var
  2232. i, refargs: SizeInt;
  2233. begin
  2234. i := 0;
  2235. refargs := 0;
  2236. SetLength(fRefArgs, Length(fArgs));
  2237. while i < Length(fArgs) do begin
  2238. if (fArgs[i].ParamFlags * [pfVar, pfOut] <> []) and not (pfHidden in fArgs[i].ParamFlags) then begin
  2239. fRefArgs[refargs] := fArgLen;
  2240. Inc(refargs);
  2241. end;
  2242. if pfArray in fArgs[i].ParamFlags then begin
  2243. Inc(i);
  2244. if (i = Length(fArgs)) or not (pfHigh in fArgs[i].ParamFlags) then
  2245. raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
  2246. Inc(fArgLen);
  2247. end else if not (pfHidden in fArgs[i].ParamFlags) or (pfSelf in fArgs[i].ParamFlags) then
  2248. Inc(fArgLen)
  2249. else if (pfResult in fArgs[i].ParamFlags) then
  2250. fResult := fArgs[i].ParamType;
  2251. Inc(i);
  2252. end;
  2253. SetLength(fRefArgs, refargs);
  2254. end;
  2255. procedure TMethodImplementation.HandleCallback(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer);
  2256. var
  2257. i, argidx: SizeInt;
  2258. args: TValueArray;
  2259. res: TValue;
  2260. begin
  2261. Assert(fArgLen = Length(aArgs), 'Length of arguments does not match');
  2262. SetLength(args, fArgLen);
  2263. argidx := 0;
  2264. i := 0;
  2265. while i < Length(fArgs) do begin
  2266. if pfArray in fArgs[i].ParamFlags then begin
  2267. Inc(i);
  2268. Assert((i < Length(fArgs)) and (pfHigh in fArgs[i].ParamFlags), 'Expected high parameter after open array parameter');
  2269. TValue.MakeOpenArray(aArgs[i - 1], SizeInt(aArgs[i]), fArgs[i].ParamType, args[argidx]);
  2270. end else if not (pfHidden in fArgs[i].ParamFlags) or (pfSelf in fArgs[i].ParamFlags) then begin
  2271. TValue.Make(aArgs[i], fArgs[i].ParamType, args[argidx]);
  2272. end;
  2273. Inc(i);
  2274. Inc(argidx);
  2275. end;
  2276. if Assigned(fCallbackMethod) then
  2277. fCallbackMethod(aContext, args, res)
  2278. else
  2279. fCallbackProc(aContext, args, res);
  2280. { copy back var/out parameters }
  2281. for i := 0 to High(fRefArgs) do begin
  2282. args[fRefArgs[i]].ExtractRawData(aArgs[fRefArgs[i]]);
  2283. end;
  2284. if Assigned(fResult) then
  2285. res.ExtractRawData(aResult);
  2286. end;
  2287. constructor TMethodImplementation.Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackMethod);
  2288. begin
  2289. fCC := aCC;
  2290. fArgs := aArgs;
  2291. fResult := aResult;
  2292. fFlags := aFlags;
  2293. fCallbackMethod := aCallback;
  2294. InitArgs;
  2295. fLowLevelCallback := CreateCallbackMethod(@HandleCallback, fCC, aArgs, aResult, aFlags, aUserData);
  2296. if not Assigned(fLowLevelCallback) then
  2297. raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
  2298. end;
  2299. constructor TMethodImplementation.Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackProc);
  2300. begin
  2301. fCC := aCC;
  2302. fArgs := aArgs;
  2303. fResult := aResult;
  2304. fFlags := aFlags;
  2305. fCallbackProc := aCallback;
  2306. InitArgs;
  2307. fLowLevelCallback := CreateCallbackMethod(@HandleCallback, fCC, aArgs, aResult, aFlags, aUserData);
  2308. if not Assigned(fLowLevelCallback) then
  2309. raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
  2310. end;
  2311. constructor TMethodImplementation.Create;
  2312. begin
  2313. raise EInvalidOpException.Create(SErrMethodImplCreateNoArg);
  2314. end;
  2315. destructor TMethodImplementation.Destroy;
  2316. begin
  2317. fLowLevelCallback.Free;
  2318. inherited Destroy;
  2319. end;
  2320. { TRttiMethod }
  2321. function TRttiMethod.GetHasExtendedInfo: Boolean;
  2322. begin
  2323. Result := False;
  2324. end;
  2325. function TRttiMethod.ToString: String;
  2326. var
  2327. ret: TRttiType;
  2328. n: String;
  2329. params: specialize TArray<TRttiParameter>;
  2330. i: LongInt;
  2331. begin
  2332. if FString = '' then begin
  2333. n := Name;
  2334. if n = '' then
  2335. n := '<unknown>';
  2336. if not HasExtendedInfo then begin
  2337. FString := 'method ' + n;
  2338. end else begin
  2339. ret := ReturnType;
  2340. if IsClassMethod then
  2341. FString := 'class ';
  2342. if IsConstructor then
  2343. FString := FString + 'constructor'
  2344. else if IsDestructor then
  2345. FString := FString + 'destructor'
  2346. else if Assigned(ret) then
  2347. FString := FString + 'function'
  2348. else
  2349. FString := FString + 'procedure';
  2350. FString := FString + ' ' + n;
  2351. params := GetParameters;
  2352. if Length(params) > 0 then begin
  2353. FString := FString + '(';
  2354. for i := 0 to High(params) do begin
  2355. if i > 0 then
  2356. FString := FString + '; ';
  2357. FString := FString + params[i].ToString;
  2358. end;
  2359. FString := FString + ')';
  2360. end;
  2361. if Assigned(ret) then
  2362. FString := FString + ': ' + ret.Name;
  2363. if IsStatic then
  2364. FString := FString + '; static';
  2365. end;
  2366. end;
  2367. Result := FString;
  2368. end;
  2369. function TRttiMethod.GetParameters: specialize TArray<TRttiParameter>;
  2370. begin
  2371. Result := GetParameters(False);
  2372. end;
  2373. function TRttiMethod.Invoke(aInstance: TObject; const aArgs: array of TValue): TValue;
  2374. var
  2375. instance: TValue;
  2376. begin
  2377. TValue.Make(@aInstance, TypeInfo(TObject), instance);
  2378. Result := Invoke(instance, aArgs);
  2379. end;
  2380. function TRttiMethod.Invoke(aInstance: TClass; const aArgs: array of TValue): TValue;
  2381. var
  2382. instance: TValue;
  2383. begin
  2384. TValue.Make(@aInstance, TypeInfo(TClass), instance);
  2385. Result := Invoke(instance, aArgs);
  2386. end;
  2387. function TRttiMethod.Invoke(aInstance: TValue; const aArgs: array of TValue): TValue;
  2388. var
  2389. addr: CodePointer;
  2390. vmt: PCodePointer;
  2391. begin
  2392. if not HasExtendedInfo then
  2393. raise EInvocationError.Create(SErrInvokeInsufficientRtti);
  2394. if IsStatic and not aInstance.IsEmpty then
  2395. raise EInvocationError.CreateFmt(SErrInvokeStaticNoSelf, [Name]);
  2396. if not IsStatic and aInstance.IsEmpty then
  2397. raise EInvocationError.CreateFmt(SErrInvokeNotStaticNeedsSelf, [Name]);
  2398. if not IsStatic and IsClassMethod and not aInstance.IsClass then
  2399. raise EInvocationError.CreateFmt(SErrInvokeClassMethodClassSelf, [Name]);
  2400. addr := Nil;
  2401. if IsStatic then
  2402. addr := CodeAddress
  2403. else begin
  2404. vmt := Nil;
  2405. if aInstance.Kind in [tkInterface, tkInterfaceRaw] then
  2406. vmt := PCodePointer(PPPointer(aInstance.GetReferenceToRawData)^^);
  2407. { ToDo }
  2408. if Assigned(vmt) then
  2409. addr := vmt[VirtualIndex];
  2410. end;
  2411. Result := Rtti.Invoke(Name, addr, CallingConvention, IsStatic, aInstance, aArgs, GetParameters(True), ReturnType);
  2412. end;
  2413. { TRttiInvokableType }
  2414. function TRttiInvokableType.GetParameters: specialize TArray<TRttiParameter>;
  2415. begin
  2416. Result := GetParameters(False);
  2417. end;
  2418. function TRttiInvokableType.CreateImplementation(aCallback: TCallbackMethod): TMethodImplementation;
  2419. var
  2420. params: specialize TArray<TRttiParameter>;
  2421. args: specialize TArray<TFunctionCallParameterInfo>;
  2422. res: PTypeInfo;
  2423. restype: TRttiType;
  2424. resinparam: Boolean;
  2425. i: SizeInt;
  2426. begin
  2427. if not Assigned(aCallback) then
  2428. raise EArgumentNilException.Create(SErrMethodImplNoCallback);
  2429. resinparam := False;
  2430. params := GetParameters(True);
  2431. SetLength(args, Length(params));
  2432. for i := 0 to High(params) do begin
  2433. args[i].ParamType := params[i].ParamType.FTypeInfo;
  2434. args[i].ParamFlags := params[i].Flags;
  2435. args[i].ParaLocs := Nil;
  2436. if pfResult in params[i].Flags then
  2437. resinparam := True;
  2438. end;
  2439. restype := GetReturnType;
  2440. if Assigned(restype) and not resinparam then
  2441. res := restype.FTypeInfo
  2442. else
  2443. res := Nil;
  2444. Result := TMethodImplementation.Create(GetCallingConvention, args, res, GetFlags, Self, TMethodImplementationCallbackMethod(aCallback));
  2445. end;
  2446. function TRttiInvokableType.CreateImplementation(aCallback: TCallbackProc): TMethodImplementation;
  2447. var
  2448. params: specialize TArray<TRttiParameter>;
  2449. args: specialize TArray<TFunctionCallParameterInfo>;
  2450. res: PTypeInfo;
  2451. restype: TRttiType;
  2452. resinparam: Boolean;
  2453. i: SizeInt;
  2454. begin
  2455. if not Assigned(aCallback) then
  2456. raise EArgumentNilException.Create(SErrMethodImplNoCallback);
  2457. resinparam := False;
  2458. params := GetParameters(True);
  2459. SetLength(args, Length(params));
  2460. for i := 0 to High(params) do begin
  2461. args[i].ParamType := params[i].ParamType.FTypeInfo;
  2462. args[i].ParamFlags := params[i].Flags;
  2463. args[i].ParaLocs := Nil;
  2464. if pfResult in params[i].Flags then
  2465. resinparam := True;
  2466. end;
  2467. restype := GetReturnType;
  2468. if Assigned(restype) and not resinparam then
  2469. res := restype.FTypeInfo
  2470. else
  2471. res := Nil;
  2472. Result := TMethodImplementation.Create(GetCallingConvention, args, res, GetFlags, Self, TMethodImplementationCallbackProc(aCallback));
  2473. end;
  2474. { TRttiMethodType }
  2475. function TRttiMethodType.GetParameters(aWithHidden: Boolean): specialize TArray<TRttiParameter>;
  2476. type
  2477. TParamInfo = record
  2478. Handle: Pointer;
  2479. Flags: TParamFlags;
  2480. Name: String;
  2481. end;
  2482. PParamFlags = ^TParamFlags;
  2483. PCallConv = ^TCallConv;
  2484. PPPTypeInfo = ^PPTypeInfo;
  2485. var
  2486. infos: array of TParamInfo;
  2487. total, visible, i: SizeInt;
  2488. ptr: PByte;
  2489. paramtypes: PPPTypeInfo;
  2490. context: TRttiContext;
  2491. obj: TRttiObject;
  2492. begin
  2493. if aWithHidden and (Length(FParamsAll) > 0) then
  2494. Exit(FParamsAll);
  2495. if not aWithHidden and (Length(FParams) > 0) then
  2496. Exit(FParams);
  2497. ptr := @FTypeData^.ParamList[0];
  2498. visible := 0;
  2499. total := 0;
  2500. if FTypeData^.ParamCount > 0 then begin
  2501. SetLength(infos, FTypeData^.ParamCount);
  2502. while total < FTypeData^.ParamCount do begin
  2503. infos[total].Handle := ptr;
  2504. infos[total].Flags := PParamFlags(ptr)^;
  2505. Inc(ptr, SizeOf(TParamFlags));
  2506. { handle name }
  2507. infos[total].Name := PShortString(ptr)^;
  2508. Inc(ptr, ptr^ + SizeOf(Byte));
  2509. { skip type name }
  2510. Inc(ptr, ptr^ + SizeOf(Byte));
  2511. { align? }
  2512. if not (pfHidden in infos[total].Flags) then
  2513. Inc(visible);
  2514. Inc(total);
  2515. end;
  2516. end;
  2517. if FTypeData^.MethodKind in [mkFunction, mkClassFunction] then begin
  2518. { skip return type name }
  2519. ptr := AlignTypeData(PByte(ptr) + ptr^ + SizeOf(Byte));
  2520. { handle return type }
  2521. FReturnType := GRttiPool.GetType(PPPTypeInfo(ptr)^^);
  2522. Inc(ptr, SizeOf(PPTypeInfo));
  2523. end;
  2524. { handle calling convention }
  2525. FCallConv := PCallConv(ptr)^;
  2526. Inc(ptr, SizeOf(TCallConv));
  2527. SetLength(FParamsAll, FTypeData^.ParamCount);
  2528. SetLength(FParams, visible);
  2529. if FTypeData^.ParamCount > 0 then begin
  2530. context := TRttiContext.Create;
  2531. try
  2532. paramtypes := PPPTypeInfo(ptr);
  2533. visible := 0;
  2534. for i := 0 to FTypeData^.ParamCount - 1 do begin
  2535. obj := context.GetByHandle(infos[i].Handle);
  2536. if Assigned(obj) then
  2537. FParamsAll[i] := obj as TRttiMethodTypeParameter
  2538. else begin
  2539. FParamsAll[i] := TRttiMethodTypeParameter.Create(infos[i].Handle, infos[i].Name, infos[i].Flags, paramtypes[i]^);
  2540. context.AddObject(FParamsAll[i]);
  2541. end;
  2542. if not (pfHidden in infos[i].Flags) then begin
  2543. FParams[visible] := FParamsAll[i];
  2544. Inc(visible);
  2545. end;
  2546. end;
  2547. finally
  2548. context.Free;
  2549. end;
  2550. end;
  2551. if aWithHidden then
  2552. Result := FParamsAll
  2553. else
  2554. Result := FParams;
  2555. end;
  2556. function TRttiMethodType.GetCallingConvention: TCallConv;
  2557. begin
  2558. { the calling convention is located after the parameters, so get the parameters
  2559. which will also initialize the calling convention }
  2560. GetParameters(True);
  2561. Result := FCallConv;
  2562. end;
  2563. function TRttiMethodType.GetReturnType: TRttiType;
  2564. begin
  2565. if FTypeData^.MethodKind in [mkFunction, mkClassFunction] then begin
  2566. { the return type is located after the parameters, so get the parameters
  2567. which will also initialize the return type }
  2568. GetParameters(True);
  2569. Result := FReturnType;
  2570. end else
  2571. Result := Nil;
  2572. end;
  2573. function TRttiMethodType.GetFlags: TFunctionCallFlags;
  2574. begin
  2575. Result := [];
  2576. end;
  2577. function TRttiMethodType.Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue;
  2578. var
  2579. method: PMethod;
  2580. inst: TValue;
  2581. begin
  2582. if aCallable.Kind <> tkMethod then
  2583. raise EInvocationError.CreateFmt(SErrInvokeCallableNotMethod, [Name]);
  2584. method := PMethod(aCallable.GetReferenceToRawData);
  2585. { by using a pointer we can also use this for non-class instance methods }
  2586. TValue.Make(@method^.Data, PTypeInfo(TypeInfo(Pointer)), inst);
  2587. Result := Rtti.Invoke(Name, method^.Code, CallingConvention, False, inst, aArgs, GetParameters(True), ReturnType);
  2588. end;
  2589. { TRttiProcedureType }
  2590. function TRttiProcedureType.GetParameters(aWithHidden: Boolean): specialize TArray<TRttiParameter>;
  2591. var
  2592. visible, i: SizeInt;
  2593. param: PProcedureParam;
  2594. obj: TRttiObject;
  2595. context: TRttiContext;
  2596. begin
  2597. if aWithHidden and (Length(FParamsAll) > 0) then
  2598. Exit(FParamsAll);
  2599. if not aWithHidden and (Length(FParams) > 0) then
  2600. Exit(FParams);
  2601. if FTypeData^.ProcSig.ParamCount = 0 then
  2602. Exit(Nil);
  2603. SetLength(FParamsAll, FTypeData^.ProcSig.ParamCount);
  2604. SetLength(FParams, FTypeData^.ProcSig.ParamCount);
  2605. context := TRttiContext.Create;
  2606. try
  2607. param := AlignTypeData(PProcedureParam(@FTypeData^.ProcSig.ParamCount + SizeOf(FTypeData^.ProcSig.ParamCount)));
  2608. visible := 0;
  2609. for i := 0 to FTypeData^.ProcSig.ParamCount - 1 do begin
  2610. obj := context.GetByHandle(param);
  2611. if Assigned(obj) then
  2612. FParamsAll[i] := obj as TRttiMethodTypeParameter
  2613. else begin
  2614. FParamsAll[i] := TRttiMethodTypeParameter.Create(param, param^.Name, param^.ParamFlags, param^.ParamType);
  2615. context.AddObject(FParamsAll[i]);
  2616. end;
  2617. if not (pfHidden in param^.ParamFlags) then begin
  2618. FParams[visible] := FParamsAll[i];
  2619. Inc(visible);
  2620. end;
  2621. param := PProcedureParam(AlignTypeData(PByte(@param^.Name) + Length(param^.Name) + SizeOf(param^.Name[0])));
  2622. end;
  2623. SetLength(FParams, visible);
  2624. finally
  2625. context.Free;
  2626. end;
  2627. if aWithHidden then
  2628. Result := FParamsAll
  2629. else
  2630. Result := FParams;
  2631. end;
  2632. function TRttiProcedureType.GetCallingConvention: TCallConv;
  2633. begin
  2634. Result := FTypeData^.ProcSig.CC;
  2635. end;
  2636. function TRttiProcedureType.GetReturnType: TRttiType;
  2637. var
  2638. context: TRttiContext;
  2639. begin
  2640. if not Assigned(FTypeData^.ProcSig.ResultTypeRef) then
  2641. Exit(Nil);
  2642. context := TRttiContext.Create;
  2643. try
  2644. Result := context.GetType(FTypeData^.ProcSig.ResultTypeRef^);
  2645. finally
  2646. context.Free;
  2647. end;
  2648. end;
  2649. function TRttiProcedureType.GetFlags: TFunctionCallFlags;
  2650. begin
  2651. Result := [fcfStatic];
  2652. end;
  2653. function TRttiProcedureType.Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue;
  2654. begin
  2655. if aCallable.Kind <> tkProcVar then
  2656. raise EInvocationError.CreateFmt(SErrInvokeCallableNotProc, [Name]);
  2657. Result := Rtti.Invoke(Name, PCodePointer(aCallable.GetReferenceToRawData)^, CallingConvention, True, TValue.Empty, aArgs, GetParameters(True), ReturnType);
  2658. end;
  2659. { TRttiStringType }
  2660. function TRttiStringType.GetStringKind: TRttiStringKind;
  2661. begin
  2662. case TypeKind of
  2663. tkSString : result := skShortString;
  2664. tkLString : result := skAnsiString;
  2665. tkAString : result := skAnsiString;
  2666. tkUString : result := skUnicodeString;
  2667. tkWString : result := skWideString;
  2668. end;
  2669. end;
  2670. { TRttiInterfaceType }
  2671. function TRttiInterfaceType.IntfMethodCount: Word;
  2672. var
  2673. parent: TRttiInterfaceType;
  2674. table: PIntfMethodTable;
  2675. begin
  2676. parent := GetIntfBaseType;
  2677. if Assigned(parent) then
  2678. Result := parent.IntfMethodCount
  2679. else
  2680. Result := 0;
  2681. table := MethodTable;
  2682. if Assigned(table) then
  2683. Inc(Result, table^.Count);
  2684. end;
  2685. function TRttiInterfaceType.GetBaseType: TRttiType;
  2686. begin
  2687. Result := GetIntfBaseType;
  2688. end;
  2689. function TRttiInterfaceType.GetGUIDStr: String;
  2690. begin
  2691. Result := GUIDToString(GUID);
  2692. end;
  2693. function TRttiInterfaceType.GetDeclaredMethods: specialize TArray<TRttiMethod>;
  2694. var
  2695. methtable: PIntfMethodTable;
  2696. count, index: Word;
  2697. method: PIntfMethodEntry;
  2698. context: TRttiContext;
  2699. obj: TRttiObject;
  2700. parent: TRttiInterfaceType;
  2701. parentmethodcount: Word;
  2702. begin
  2703. if Assigned(fDeclaredMethods) then
  2704. Exit(fDeclaredMethods);
  2705. methtable := MethodTable;
  2706. if not Assigned(methtable) then
  2707. Exit(Nil);
  2708. if (methtable^.Count = 0) or (methtable^.RTTICount = $ffff) then
  2709. Exit(Nil);
  2710. parent := GetIntfBaseType;
  2711. if Assigned(parent) then
  2712. parentmethodcount := parent.IntfMethodCount
  2713. else
  2714. parentmethodcount := 0;
  2715. SetLength(fDeclaredMethods, methtable^.Count);
  2716. context := TRttiContext.Create;
  2717. try
  2718. method := methtable^.Method[0];
  2719. count := methtable^.Count;
  2720. while count > 0 do begin
  2721. index := methtable^.Count - count;
  2722. obj := context.GetByHandle(method);
  2723. if Assigned(obj) then
  2724. fDeclaredMethods[index] := obj as TRttiMethod
  2725. else begin
  2726. fDeclaredMethods[index] := TRttiIntfMethod.Create(Self, method, parentmethodcount + index);
  2727. context.AddObject(fDeclaredMethods[index]);
  2728. end;
  2729. method := method^.Next;
  2730. Dec(count);
  2731. end;
  2732. finally
  2733. context.Free;
  2734. end;
  2735. Result := fDeclaredMethods;
  2736. end;
  2737. { TRttiInstanceType }
  2738. function TRttiInstanceType.GetMetaClassType: TClass;
  2739. begin
  2740. result := FTypeData^.ClassType;
  2741. end;
  2742. function TRttiInstanceType.GetDeclaringUnitName: string;
  2743. begin
  2744. result := FTypeData^.UnitName;
  2745. end;
  2746. function TRttiInstanceType.GetBaseType: TRttiType;
  2747. var
  2748. AContext: TRttiContext;
  2749. begin
  2750. AContext := TRttiContext.Create;
  2751. try
  2752. result := AContext.GetType(FTypeData^.ParentInfo);
  2753. finally
  2754. AContext.Free;
  2755. end;
  2756. end;
  2757. function TRttiInstanceType.GetIsInstance: boolean;
  2758. begin
  2759. Result:=True;
  2760. end;
  2761. function TRttiInstanceType.GetTypeSize: integer;
  2762. begin
  2763. Result:=sizeof(TObject);
  2764. end;
  2765. function TRttiInstanceType.GetProperties: specialize TArray<TRttiProperty>;
  2766. var
  2767. TypeInfo: PTypeInfo;
  2768. TypeRttiType: TRttiType;
  2769. TD: PTypeData;
  2770. PPD: PPropData;
  2771. TP: PPropInfo;
  2772. Count: longint;
  2773. obj: TRttiObject;
  2774. begin
  2775. if not FPropertiesResolved then
  2776. begin
  2777. TypeInfo := FTypeInfo;
  2778. // Get the total properties count
  2779. SetLength(FProperties,FTypeData^.PropCount);
  2780. TypeRttiType:= self;
  2781. repeat
  2782. TD:=GetTypeData(TypeInfo);
  2783. // published properties count for this object
  2784. // skip the attribute-info if available
  2785. PPD := PClassData(TD)^.PropertyTable;
  2786. Count:=PPD^.PropCount;
  2787. // Now point TP to first propinfo record.
  2788. TP:=PPropInfo(@PPD^.PropList);
  2789. While Count>0 do
  2790. begin
  2791. // Don't overwrite properties with the same name
  2792. if FProperties[TP^.NameIndex]=nil then begin
  2793. obj := GRttiPool.GetByHandle(TP);
  2794. if Assigned(obj) then
  2795. FProperties[TP^.NameIndex] := obj as TRttiProperty
  2796. else begin
  2797. FProperties[TP^.NameIndex] := TRttiProperty.Create(TypeRttiType, TP);
  2798. GRttiPool.AddObject(FProperties[TP^.NameIndex]);
  2799. end;
  2800. end;
  2801. // Point to TP next propinfo record.
  2802. // Located at Name[Length(Name)+1] !
  2803. TP:=TP^.Next;
  2804. Dec(Count);
  2805. end;
  2806. TypeInfo:=TD^.Parentinfo;
  2807. TypeRttiType:= GRttiPool.GetType(TypeInfo);
  2808. until TypeInfo=nil;
  2809. end;
  2810. result := FProperties;
  2811. end;
  2812. { TRttiMember }
  2813. function TRttiMember.GetVisibility: TMemberVisibility;
  2814. begin
  2815. result := mvPublished;
  2816. end;
  2817. constructor TRttiMember.Create(AParent: TRttiType);
  2818. begin
  2819. inherited Create();
  2820. FParent := AParent;
  2821. end;
  2822. { TRttiProperty }
  2823. function TRttiProperty.GetPropertyType: TRttiType;
  2824. begin
  2825. result := GRttiPool.GetType(FPropInfo^.PropType);
  2826. end;
  2827. function TRttiProperty.GetIsReadable: boolean;
  2828. begin
  2829. result := assigned(FPropInfo^.GetProc);
  2830. end;
  2831. function TRttiProperty.GetIsWritable: boolean;
  2832. begin
  2833. result := assigned(FPropInfo^.SetProc);
  2834. end;
  2835. function TRttiProperty.GetVisibility: TMemberVisibility;
  2836. begin
  2837. // At this moment only pulished rtti-property-info is supported by fpc
  2838. result := mvPublished;
  2839. end;
  2840. function TRttiProperty.GetName: string;
  2841. begin
  2842. Result:=FPropInfo^.Name;
  2843. end;
  2844. function TRttiProperty.GetHandle: Pointer;
  2845. begin
  2846. Result := FPropInfo;
  2847. end;
  2848. constructor TRttiProperty.Create(AParent: TRttiType; APropInfo: PPropInfo);
  2849. begin
  2850. inherited Create(AParent);
  2851. FPropInfo := APropInfo;
  2852. end;
  2853. function TRttiProperty.GetValue(Instance: pointer): TValue;
  2854. procedure ValueFromBool(value: Int64);
  2855. var
  2856. b8: Boolean;
  2857. b16: Boolean16;
  2858. b32: Boolean32;
  2859. bb: ByteBool;
  2860. bw: WordBool;
  2861. bl: LongBool;
  2862. td: PTypeData;
  2863. p: Pointer;
  2864. begin
  2865. td := GetTypeData(FPropInfo^.PropType);
  2866. case td^.OrdType of
  2867. otUByte:
  2868. begin
  2869. b8 := Boolean(value);
  2870. p := @b8;
  2871. end;
  2872. otUWord:
  2873. begin
  2874. b16 := Boolean16(value);
  2875. p := @b16;
  2876. end;
  2877. otULong:
  2878. begin
  2879. b32 := Boolean32(value);
  2880. p := @b32;
  2881. end;
  2882. otSByte:
  2883. begin
  2884. bb := ByteBool(value);
  2885. p := @bb;
  2886. end;
  2887. otSWord:
  2888. begin
  2889. bw := WordBool(value);
  2890. p := @bw;
  2891. end;
  2892. otSLong:
  2893. begin
  2894. bl := LongBool(value);
  2895. p := @bl;
  2896. end;
  2897. end;
  2898. TValue.Make(p, FPropInfo^.PropType, result);
  2899. end;
  2900. procedure ValueFromInt(value: Int64);
  2901. var
  2902. i8: UInt8;
  2903. i16: UInt16;
  2904. i32: UInt32;
  2905. td: PTypeData;
  2906. p: Pointer;
  2907. begin
  2908. td := GetTypeData(FPropInfo^.PropType);
  2909. case td^.OrdType of
  2910. otUByte,
  2911. otSByte:
  2912. begin
  2913. i8 := value;
  2914. p := @i8;
  2915. end;
  2916. otUWord,
  2917. otSWord:
  2918. begin
  2919. i16 := value;
  2920. p := @i16;
  2921. end;
  2922. otULong,
  2923. otSLong:
  2924. begin
  2925. i32 := value;
  2926. p := @i32;
  2927. end;
  2928. end;
  2929. TValue.Make(p, FPropInfo^.PropType, result);
  2930. end;
  2931. var
  2932. s: string;
  2933. ss: ShortString;
  2934. i: int64;
  2935. c: Char;
  2936. wc: WideChar;
  2937. begin
  2938. case FPropinfo^.PropType^.Kind of
  2939. tkSString:
  2940. begin
  2941. ss := GetStrProp(TObject(Instance), FPropInfo);
  2942. TValue.Make(@ss, FPropInfo^.PropType, result);
  2943. end;
  2944. tkAString:
  2945. begin
  2946. s := GetStrProp(TObject(Instance), FPropInfo);
  2947. TValue.Make(@s, FPropInfo^.PropType, result);
  2948. end;
  2949. tkBool:
  2950. begin
  2951. i := GetOrdProp(TObject(Instance), FPropInfo);
  2952. ValueFromBool(i);
  2953. end;
  2954. tkInteger:
  2955. begin
  2956. i := GetOrdProp(TObject(Instance), FPropInfo);
  2957. ValueFromInt(i);
  2958. end;
  2959. tkChar:
  2960. begin
  2961. c := AnsiChar(GetOrdProp(TObject(Instance), FPropInfo));
  2962. TValue.Make(@c, FPropInfo^.PropType, result);
  2963. end;
  2964. tkWChar:
  2965. begin
  2966. wc := WideChar(GetOrdProp(TObject(Instance), FPropInfo));
  2967. TValue.Make(@wc, FPropInfo^.PropType, result);
  2968. end;
  2969. tkInt64,
  2970. tkQWord:
  2971. begin
  2972. i := GetOrdProp(TObject(Instance), FPropInfo);
  2973. TValue.Make(@i, FPropInfo^.PropType, result);
  2974. end;
  2975. else
  2976. result := TValue.Empty;
  2977. end
  2978. end;
  2979. procedure TRttiProperty.SetValue(Instance: pointer; const AValue: TValue);
  2980. begin
  2981. case FPropinfo^.PropType^.Kind of
  2982. tkSString,
  2983. tkAString:
  2984. SetStrProp(TObject(Instance), FPropInfo, AValue.AsString);
  2985. tkInteger,
  2986. tkInt64,
  2987. tkQWord,
  2988. tkChar,
  2989. tkBool,
  2990. tkWChar:
  2991. SetOrdProp(TObject(Instance), FPropInfo, AValue.AsOrdinal);
  2992. else
  2993. raise exception.createFmt(SErrUnableToSetValueForType, [PropertyType.Name]);
  2994. end
  2995. end;
  2996. function TRttiType.GetIsInstance: boolean;
  2997. begin
  2998. result := false;
  2999. end;
  3000. function TRttiType.GetIsManaged: boolean;
  3001. begin
  3002. result := Rtti.IsManaged(FTypeInfo);
  3003. end;
  3004. function TRttiType.GetIsOrdinal: boolean;
  3005. begin
  3006. result := false;
  3007. end;
  3008. function TRttiType.GetIsRecord: boolean;
  3009. begin
  3010. result := false;
  3011. end;
  3012. function TRttiType.GetIsSet: boolean;
  3013. begin
  3014. result := false;
  3015. end;
  3016. function TRttiType.GetAsInstance: TRttiInstanceType;
  3017. begin
  3018. // This is a ridicoulous design, but Delphi-compatible...
  3019. result := TRttiInstanceType(self);
  3020. end;
  3021. function TRttiType.GetBaseType: TRttiType;
  3022. begin
  3023. result := nil;
  3024. end;
  3025. function TRttiType.GetTypeKind: TTypeKind;
  3026. begin
  3027. result := FTypeInfo^.Kind;
  3028. end;
  3029. function TRttiType.GetTypeSize: integer;
  3030. begin
  3031. result := -1;
  3032. end;
  3033. function TRttiType.GetName: string;
  3034. begin
  3035. Result:=FTypeInfo^.Name;
  3036. end;
  3037. function TRttiType.GetHandle: Pointer;
  3038. begin
  3039. Result := FTypeInfo;
  3040. end;
  3041. constructor TRttiType.Create(ATypeInfo: PTypeInfo);
  3042. begin
  3043. inherited Create();
  3044. FTypeInfo:=ATypeInfo;
  3045. if assigned(FTypeInfo) then
  3046. FTypeData:=GetTypeData(ATypeInfo);
  3047. end;
  3048. function TRttiType.GetProperties: specialize TArray<TRttiProperty>;
  3049. begin
  3050. Result := Nil;
  3051. end;
  3052. function TRttiType.GetProperty(const AName: string): TRttiProperty;
  3053. var
  3054. FPropList: specialize TArray<TRttiProperty>;
  3055. i: Integer;
  3056. begin
  3057. result := nil;
  3058. FPropList := GetProperties;
  3059. for i := 0 to length(FPropList)-1 do
  3060. if sametext(FPropList[i].Name,AName) then
  3061. begin
  3062. result := FPropList[i];
  3063. break;
  3064. end;
  3065. end;
  3066. function TRttiType.GetMethods: specialize TArray<TRttiMethod>;
  3067. var
  3068. parentmethods, selfmethods: specialize TArray<TRttiMethod>;
  3069. parent: TRttiType;
  3070. begin
  3071. if Assigned(fMethods) then
  3072. Exit(fMethods);
  3073. selfmethods := GetDeclaredMethods;
  3074. parent := GetBaseType;
  3075. if Assigned(parent) then begin
  3076. parentmethods := parent.GetMethods;
  3077. end;
  3078. fMethods := Concat(parentmethods, selfmethods);
  3079. Result := fMethods;
  3080. end;
  3081. function TRttiType.GetMethod(const aName: String): TRttiMethod;
  3082. var
  3083. methods: specialize TArray<TRttiMethod>;
  3084. method: TRttiMethod;
  3085. begin
  3086. methods := GetMethods;
  3087. for method in methods do
  3088. if SameText(method.Name, AName) then
  3089. Exit(method);
  3090. Result := Nil;
  3091. end;
  3092. function TRttiType.GetDeclaredMethods: specialize TArray<TRttiMethod>;
  3093. begin
  3094. Result := Nil;
  3095. end;
  3096. { TRttiNamedObject }
  3097. function TRttiNamedObject.GetName: string;
  3098. begin
  3099. result := '';
  3100. end;
  3101. { TRttiContext }
  3102. class function TRttiContext.Create: TRttiContext;
  3103. begin
  3104. result.FContextToken := nil;
  3105. end;
  3106. procedure TRttiContext.Free;
  3107. begin
  3108. FContextToken := nil;
  3109. end;
  3110. function TRttiContext.GetByHandle(AHandle: Pointer): TRttiObject;
  3111. begin
  3112. if not Assigned(FContextToken) then
  3113. FContextToken := TPoolToken.Create;
  3114. Result := (FContextToken as IPooltoken).RttiPool.GetByHandle(AHandle);
  3115. end;
  3116. procedure TRttiContext.AddObject(AObject: TRttiObject);
  3117. begin
  3118. if not Assigned(FContextToken) then
  3119. FContextToken := TPoolToken.Create;
  3120. (FContextToken as IPooltoken).RttiPool.AddObject(AObject);
  3121. end;
  3122. function TRttiContext.GetType(ATypeInfo: PTypeInfo): TRttiType;
  3123. begin
  3124. if not assigned(FContextToken) then
  3125. FContextToken := TPoolToken.Create;
  3126. result := (FContextToken as IPooltoken).RttiPool.GetType(ATypeInfo);
  3127. end;
  3128. function TRttiContext.GetType(AClass: TClass): TRttiType;
  3129. begin
  3130. if assigned(AClass) then
  3131. result := GetType(PTypeInfo(AClass.ClassInfo))
  3132. else
  3133. result := nil;
  3134. end;
  3135. {function TRttiContext.GetTypes: specialize TArray<TRttiType>;
  3136. begin
  3137. if not assigned(FContextToken) then
  3138. FContextToken := TPoolToken.Create;
  3139. result := (FContextToken as IPooltoken).RttiPool.GetTypes;
  3140. end;}
  3141. {$ifndef InLazIDE}
  3142. {$if defined(CPUI386) or (defined(CPUX86_64) and defined(WIN64))}
  3143. {$I invoke.inc}
  3144. {$endif}
  3145. {$endif}
  3146. initialization
  3147. PoolRefCount := 0;
  3148. InitDefaultFunctionCallManager;
  3149. {$ifdef SYSTEM_HAS_INVOKE}
  3150. InitSystemFunctionCallManager;
  3151. {$endif}
  3152. end.