rtti.pp 103 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585
  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. { TRttiPool }
  768. function TRttiPool.GetTypes: specialize TArray<TRttiType>;
  769. begin
  770. if not Assigned(FTypesList) then
  771. Exit(Nil);
  772. {$ifdef FPC_HAS_FEATURE_THREADING}
  773. EnterCriticalsection(FLock);
  774. try
  775. {$endif}
  776. Result := Copy(FTypesList, 0, FTypeCount);
  777. {$ifdef FPC_HAS_FEATURE_THREADING}
  778. finally
  779. LeaveCriticalsection(FLock);
  780. end;
  781. {$endif}
  782. end;
  783. function TRttiPool.GetType(ATypeInfo: PTypeInfo): TRttiType;
  784. var
  785. obj: TRttiObject;
  786. begin
  787. if not Assigned(ATypeInfo) then
  788. Exit(Nil);
  789. {$ifdef FPC_HAS_FEATURE_THREADING}
  790. EnterCriticalsection(FLock);
  791. try
  792. {$endif}
  793. Result := Nil;
  794. obj := GetByHandle(ATypeInfo);
  795. if Assigned(obj) then
  796. Result := obj as TRttiType;
  797. if not Assigned(Result) then
  798. begin
  799. if FTypeCount = Length(FTypesList) then
  800. begin
  801. SetLength(FTypesList, FTypeCount * 2);
  802. end;
  803. case ATypeInfo^.Kind of
  804. tkClass : Result := TRttiInstanceType.Create(ATypeInfo);
  805. tkInterface: Result := TRttiRefCountedInterfaceType.Create(ATypeInfo);
  806. tkInterfaceRaw: Result := TRttiRawInterfaceType.Create(ATypeInfo);
  807. tkSString,
  808. tkLString,
  809. tkAString,
  810. tkUString,
  811. tkWString : Result := TRttiStringType.Create(ATypeInfo);
  812. tkFloat : Result := TRttiFloatType.Create(ATypeInfo);
  813. tkPointer : Result := TRttiPointerType.Create(ATypeInfo);
  814. tkProcVar : Result := TRttiProcedureType.Create(ATypeInfo);
  815. tkMethod : Result := TRttiMethodType.Create(ATypeInfo);
  816. else
  817. Result := TRttiType.Create(ATypeInfo);
  818. end;
  819. FTypesList[FTypeCount] := Result;
  820. FObjectMap.Add(ATypeInfo, Result);
  821. Inc(FTypeCount);
  822. end;
  823. {$ifdef FPC_HAS_FEATURE_THREADING}
  824. finally
  825. LeaveCriticalsection(FLock);
  826. end;
  827. {$endif}
  828. end;
  829. function TRttiPool.GetByHandle(aHandle: Pointer): TRttiObject;
  830. var
  831. idx: LongInt;
  832. begin
  833. if not Assigned(aHandle) then
  834. Exit(Nil);
  835. {$ifdef FPC_HAS_FEATURE_THREADING}
  836. EnterCriticalsection(FLock);
  837. try
  838. {$endif}
  839. idx := FObjectMap.IndexOf(aHandle);
  840. if idx < 0 then
  841. Result := Nil
  842. else
  843. Result := FObjectMap.Data[idx];
  844. {$ifdef FPC_HAS_FEATURE_THREADING}
  845. finally
  846. LeaveCriticalsection(FLock);
  847. end;
  848. {$endif}
  849. end;
  850. procedure TRttiPool.AddObject(aObject: TRttiObject);
  851. var
  852. idx: LongInt;
  853. begin
  854. if not Assigned(aObject) then
  855. Exit;
  856. if not Assigned(aObject.Handle) then
  857. raise EArgumentException.Create(SErrRttiObjectNoHandle);
  858. {$ifdef FPC_HAS_FEATURE_THREADING}
  859. EnterCriticalsection(FLock);
  860. try
  861. {$endif}
  862. idx := FObjectMap.IndexOf(aObject.Handle);
  863. if idx < 0 then
  864. FObjectMap.Add(aObject.Handle, aObject)
  865. else if FObjectMap.Data[idx] <> aObject then
  866. raise EInvalidOpException.CreateFmt(SErrRttiObjectAlreadyRegistered, [aObject.Handle]);
  867. {$ifdef FPC_HAS_FEATURE_THREADING}
  868. finally
  869. LeaveCriticalsection(FLock);
  870. end;
  871. {$endif}
  872. end;
  873. constructor TRttiPool.Create;
  874. begin
  875. {$ifdef FPC_HAS_FEATURE_THREADING}
  876. InitCriticalSection(FLock);
  877. {$endif}
  878. SetLength(FTypesList, 32);
  879. FObjectMap := TRttiObjectMap.Create;
  880. end;
  881. destructor TRttiPool.Destroy;
  882. var
  883. i: LongInt;
  884. begin
  885. for i := 0 to FObjectMap.Count - 1 do
  886. FObjectMap.Data[i].Free;
  887. FObjectMap.Free;
  888. {$ifdef FPC_HAS_FEATURE_THREADING}
  889. DoneCriticalsection(FLock);
  890. {$endif}
  891. inherited Destroy;
  892. end;
  893. { TPoolToken }
  894. constructor TPoolToken.Create;
  895. begin
  896. inherited Create;
  897. if InterlockedIncrement(PoolRefCount)=1 then
  898. GRttiPool := TRttiPool.Create;
  899. end;
  900. destructor TPoolToken.Destroy;
  901. begin
  902. if InterlockedDecrement(PoolRefCount)=0 then
  903. GRttiPool.Free;
  904. inherited;
  905. end;
  906. function TPoolToken.RttiPool: TRttiPool;
  907. begin
  908. result := GRttiPool;
  909. end;
  910. { TValueDataIntImpl }
  911. procedure IntFinalize(APointer, ATypeInfo: Pointer);
  912. external name 'FPC_FINALIZE';
  913. procedure IntInitialize(APointer, ATypeInfo: Pointer);
  914. external name 'FPC_INITIALIZE';
  915. procedure IntAddRef(APointer, ATypeInfo: Pointer);
  916. external name 'FPC_ADDREF';
  917. function IntCopy(ASource, ADest, ATypeInfo: Pointer): SizeInt;
  918. external name 'FPC_COPY';
  919. constructor TValueDataIntImpl.CreateCopy(ACopyFromBuffer: Pointer; ALen: SizeInt; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  920. begin
  921. FTypeInfo := ATypeInfo;
  922. FDataSize:=ALen;
  923. if ALen>0 then
  924. begin
  925. Getmem(FBuffer,FDataSize);
  926. if Assigned(ACopyFromBuffer) then
  927. system.move(ACopyFromBuffer^,FBuffer^,FDataSize)
  928. else
  929. FillChar(FBuffer^, FDataSize, 0);
  930. end;
  931. FIsCopy := True;
  932. FUseAddRef := AAddRef;
  933. if AAddRef and (ALen > 0) then begin
  934. if Assigned(ACopyFromBuffer) then
  935. IntAddRef(FBuffer, FTypeInfo)
  936. else
  937. IntInitialize(FBuffer, FTypeInfo);
  938. end;
  939. end;
  940. constructor TValueDataIntImpl.CreateRef(AData: Pointer; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  941. begin
  942. FTypeInfo := ATypeInfo;
  943. FDataSize := SizeOf(Pointer);
  944. if Assigned(AData) then
  945. FBuffer := PPointer(AData)^
  946. else
  947. FBuffer := Nil;
  948. FIsCopy := False;
  949. FUseAddRef := AAddRef;
  950. if AAddRef and Assigned(AData) then
  951. IntAddRef(@FBuffer, FTypeInfo);
  952. end;
  953. destructor TValueDataIntImpl.Destroy;
  954. begin
  955. if Assigned(FBuffer) then begin
  956. if FUseAddRef then
  957. if FIsCopy then
  958. IntFinalize(FBuffer, FTypeInfo)
  959. else
  960. IntFinalize(@FBuffer, FTypeInfo);
  961. if FIsCopy then
  962. Freemem(FBuffer);
  963. end;
  964. inherited Destroy;
  965. end;
  966. procedure TValueDataIntImpl.ExtractRawData(ABuffer: pointer);
  967. begin
  968. if FDataSize = 0 then
  969. Exit;
  970. if FIsCopy then
  971. System.Move(FBuffer^, ABuffer^, FDataSize)
  972. else
  973. System.Move(FBuffer{!}, ABuffer^, FDataSize);
  974. if FUseAddRef then
  975. IntAddRef(ABuffer, FTypeInfo);
  976. end;
  977. procedure TValueDataIntImpl.ExtractRawDataNoCopy(ABuffer: pointer);
  978. begin
  979. if FDataSize = 0 then
  980. Exit;
  981. if FIsCopy then
  982. system.move(FBuffer^, ABuffer^, FDataSize)
  983. else
  984. System.Move(FBuffer{!}, ABuffer^, FDataSize);
  985. end;
  986. function TValueDataIntImpl.GetDataSize: SizeInt;
  987. begin
  988. result := FDataSize;
  989. end;
  990. function TValueDataIntImpl.GetReferenceToRawData: pointer;
  991. begin
  992. if FIsCopy then
  993. result := FBuffer
  994. else
  995. result := @FBuffer;
  996. end;
  997. { TValue }
  998. class function TValue.Empty: TValue;
  999. begin
  1000. result.FData.FTypeInfo := nil;
  1001. {$if SizeOf(TMethod) > SizeOf(QWord)}
  1002. Result.FData.FAsMethod.Code := Nil;
  1003. Result.FData.FAsMethod.Data := Nil;
  1004. {$else}
  1005. Result.FData.FAsUInt64 := 0;
  1006. {$endif}
  1007. end;
  1008. function TValue.GetTypeDataProp: PTypeData;
  1009. begin
  1010. result := GetTypeData(FData.FTypeInfo);
  1011. end;
  1012. function TValue.GetTypeInfo: PTypeInfo;
  1013. begin
  1014. result := FData.FTypeInfo;
  1015. end;
  1016. function TValue.GetTypeKind: TTypeKind;
  1017. begin
  1018. if not Assigned(FData.FTypeInfo) then
  1019. Result := tkUnknown
  1020. else
  1021. result := FData.FTypeInfo^.Kind;
  1022. end;
  1023. function TValue.GetDataSize: SizeInt;
  1024. begin
  1025. if Assigned(FData.FValueData) and (Kind <> tkSString) then
  1026. Result := FData.FValueData.GetDataSize
  1027. else begin
  1028. Result := 0;
  1029. case Kind of
  1030. tkEnumeration,
  1031. tkBool,
  1032. tkInt64,
  1033. tkQWord,
  1034. tkInteger:
  1035. case TypeData^.OrdType of
  1036. otSByte,
  1037. otUByte:
  1038. Result := SizeOf(Byte);
  1039. otSWord,
  1040. otUWord:
  1041. Result := SizeOf(Word);
  1042. otSLong,
  1043. otULong:
  1044. Result := SizeOf(LongWord);
  1045. otSQWord,
  1046. otUQWord:
  1047. Result := SizeOf(QWord);
  1048. end;
  1049. tkChar:
  1050. Result := SizeOf(AnsiChar);
  1051. tkFloat:
  1052. case TypeData^.FloatType of
  1053. ftSingle:
  1054. Result := SizeOf(Single);
  1055. ftDouble:
  1056. Result := SizeOf(Double);
  1057. ftExtended:
  1058. Result := SizeOf(Extended);
  1059. ftComp:
  1060. Result := SizeOf(Comp);
  1061. ftCurr:
  1062. Result := SizeOf(Currency);
  1063. end;
  1064. tkSet:
  1065. Result := TypeData^.SetSize;
  1066. tkMethod:
  1067. Result := SizeOf(TMethod);
  1068. tkSString:
  1069. { ShortString can hold max. 254 characters as [0] is Length and [255] is #0 }
  1070. Result := SizeOf(ShortString) - 2;
  1071. tkVariant:
  1072. Result := SizeOf(Variant);
  1073. tkProcVar:
  1074. Result := SizeOf(CodePointer);
  1075. tkWChar:
  1076. Result := SizeOf(WideChar);
  1077. tkUChar:
  1078. Result := SizeOf(UnicodeChar);
  1079. tkFile:
  1080. { ToDo }
  1081. Result := SizeOf(TTextRec);
  1082. tkAString,
  1083. tkWString,
  1084. tkUString,
  1085. tkInterface,
  1086. tkDynArray,
  1087. tkClass,
  1088. tkHelper,
  1089. tkClassRef,
  1090. tkInterfaceRaw,
  1091. tkPointer:
  1092. Result := SizeOf(Pointer);
  1093. tkObject,
  1094. tkRecord:
  1095. Result := TypeData^.RecSize;
  1096. tkArray:
  1097. Result := TypeData^.ArrayData.Size;
  1098. tkUnknown,
  1099. tkLString:
  1100. Assert(False);
  1101. end;
  1102. end;
  1103. end;
  1104. class procedure TValue.Make(ABuffer: pointer; ATypeInfo: PTypeInfo; out result: TValue);
  1105. type
  1106. PBoolean16 = ^Boolean16;
  1107. PBoolean32 = ^Boolean32;
  1108. PBoolean64 = ^Boolean64;
  1109. PByteBool = ^ByteBool;
  1110. PQWordBool = ^QWordBool;
  1111. PMethod = ^TMethod;
  1112. var
  1113. td: PTypeData;
  1114. size: SizeInt;
  1115. begin
  1116. result.FData.FTypeInfo:=ATypeInfo;
  1117. { resets the whole variant part; FValueData is already Nil }
  1118. {$if SizeOf(TMethod) > SizeOf(QWord)}
  1119. Result.FData.FAsMethod.Code := Nil;
  1120. Result.FData.FAsMethod.Data := Nil;
  1121. {$else}
  1122. Result.FData.FAsUInt64 := 0;
  1123. {$endif}
  1124. if not Assigned(ATypeInfo) then
  1125. Exit;
  1126. { first handle those types that need a TValueData implementation }
  1127. case ATypeInfo^.Kind of
  1128. tkSString : begin
  1129. td := GetTypeData(ATypeInfo);
  1130. result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, td^.MaxLength + 1, ATypeInfo, True);
  1131. end;
  1132. tkWString,
  1133. tkUString,
  1134. tkAString : result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  1135. tkDynArray : result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  1136. tkArray : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, Result.TypeData^.ArrayData.Size, ATypeInfo, False);
  1137. tkObject,
  1138. tkRecord : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, Result.TypeData^.RecSize, ATypeInfo, False);
  1139. tkInterface: result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  1140. end;
  1141. if not Assigned(ABuffer) then
  1142. Exit;
  1143. { now handle those that are happy with the variant part of FData }
  1144. case ATypeInfo^.Kind of
  1145. tkSString,
  1146. tkWString,
  1147. tkUString,
  1148. tkAString,
  1149. tkDynArray,
  1150. tkArray,
  1151. tkObject,
  1152. tkRecord,
  1153. tkInterface:
  1154. { ignore }
  1155. ;
  1156. tkClass : result.FData.FAsObject := PPointer(ABuffer)^;
  1157. tkClassRef : result.FData.FAsClass := PClass(ABuffer)^;
  1158. tkInterfaceRaw : result.FData.FAsPointer := PPointer(ABuffer)^;
  1159. tkInt64 : result.FData.FAsSInt64 := PInt64(ABuffer)^;
  1160. tkQWord : result.FData.FAsUInt64 := PQWord(ABuffer)^;
  1161. tkProcVar : result.FData.FAsMethod.Code := PCodePointer(ABuffer)^;
  1162. tkMethod : result.FData.FAsMethod := PMethod(ABuffer)^;
  1163. tkPointer : result.FData.FAsPointer := PPointer(ABuffer)^;
  1164. tkSet : begin
  1165. td := GetTypeData(ATypeInfo);
  1166. case td^.OrdType of
  1167. otUByte: begin
  1168. { this can either really be 1 Byte or a set > 32-bit, so
  1169. check the underlying type }
  1170. if not (td^.CompType^.Kind in [tkInteger,tkEnumeration]) then
  1171. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  1172. case td^.SetSize of
  1173. 0, 1:
  1174. Result.FData.FAsUByte := PByte(ABuffer)^;
  1175. { these two cases shouldn't happen, but better safe than sorry... }
  1176. 2:
  1177. Result.FData.FAsUWord := PWord(ABuffer)^;
  1178. 3, 4:
  1179. Result.FData.FAsULong := PLongWord(ABuffer)^;
  1180. { maybe we should also allow storage as otUQWord? }
  1181. 5..8:
  1182. Result.FData.FAsUInt64 := PQWord(ABuffer)^;
  1183. else
  1184. Result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, td^.SetSize, ATypeInfo, False);
  1185. end;
  1186. end;
  1187. otUWord:
  1188. Result.FData.FAsUWord := PWord(ABuffer)^;
  1189. otULong:
  1190. Result.FData.FAsULong := PLongWord(ABuffer)^;
  1191. else
  1192. { ehm... Panic? }
  1193. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  1194. end;
  1195. end;
  1196. tkEnumeration,
  1197. tkInteger : begin
  1198. case GetTypeData(ATypeInfo)^.OrdType of
  1199. otSByte: result.FData.FAsSByte := PShortInt(ABuffer)^;
  1200. otUByte: result.FData.FAsUByte := PByte(ABuffer)^;
  1201. otSWord: result.FData.FAsSWord := PSmallInt(ABuffer)^;
  1202. otUWord: result.FData.FAsUWord := PWord(ABuffer)^;
  1203. otSLong: result.FData.FAsSLong := PLongInt(ABuffer)^;
  1204. otULong: result.FData.FAsULong := PLongWord(ABuffer)^;
  1205. end;
  1206. end;
  1207. tkBool : begin
  1208. case GetTypeData(ATypeInfo)^.OrdType of
  1209. otUByte: result.FData.FAsUByte := Byte(System.PBoolean(ABuffer)^);
  1210. otUWord: result.FData.FAsUWord := Word(PBoolean16(ABuffer)^);
  1211. otULong: result.FData.FAsULong := DWord(PBoolean32(ABuffer)^);
  1212. otUQWord: result.FData.FAsUInt64 := QWord(PBoolean64(ABuffer)^);
  1213. otSByte: result.FData.FAsSByte := ShortInt(PByteBool(ABuffer)^);
  1214. otSWord: result.FData.FAsSWord := SmallInt(PWordBool(ABuffer)^);
  1215. otSLong: result.FData.FAsSLong := LongInt(PLongBool(ABuffer)^);
  1216. otSQWord: result.FData.FAsSInt64 := Int64(PQWordBool(ABuffer)^);
  1217. end;
  1218. end;
  1219. tkFloat : begin
  1220. case GetTypeData(ATypeInfo)^.FloatType of
  1221. ftCurr : result.FData.FAsCurr := PCurrency(ABuffer)^;
  1222. ftSingle : result.FData.FAsSingle := PSingle(ABuffer)^;
  1223. ftDouble : result.FData.FAsDouble := PDouble(ABuffer)^;
  1224. ftExtended: result.FData.FAsExtended := PExtended(ABuffer)^;
  1225. ftComp : result.FData.FAsComp := PComp(ABuffer)^;
  1226. end;
  1227. end;
  1228. else
  1229. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  1230. end;
  1231. end;
  1232. class procedure TValue.MakeOpenArray(AArray: Pointer; ALength: SizeInt; ATypeInfo: PTypeInfo; out Result: TValue);
  1233. var
  1234. el: TValue;
  1235. begin
  1236. Result.FData.FTypeInfo := ATypeInfo;
  1237. { resets the whole variant part; FValueData is already Nil }
  1238. {$if SizeOf(TMethod) > SizeOf(QWord)}
  1239. Result.FData.FAsMethod.Code := Nil;
  1240. Result.FData.FAsMethod.Data := Nil;
  1241. {$else}
  1242. Result.FData.FAsUInt64 := 0;
  1243. {$endif}
  1244. if not Assigned(ATypeInfo) then
  1245. Exit;
  1246. if ATypeInfo^.Kind <> tkArray then
  1247. Exit;
  1248. if not Assigned(AArray) then
  1249. Exit;
  1250. if ALength < 0 then
  1251. Exit;
  1252. Result.FData.FValueData := TValueDataIntImpl.CreateRef(@AArray, ATypeInfo, False);
  1253. Result.FData.FArrLength := ALength;
  1254. Make(Nil, Result.TypeData^.ArrayData.ElType, el);
  1255. Result.FData.FElSize := el.DataSize;
  1256. end;
  1257. {$ifndef NoGenericMethods}
  1258. generic class function TValue.From<T>(constref aValue: T): TValue;
  1259. begin
  1260. TValue.Make(@aValue, System.TypeInfo(T), Result);
  1261. end;
  1262. generic class function TValue.FromOpenArray<T>(constref aValue: array of T): TValue;
  1263. var
  1264. arrdata: Pointer;
  1265. begin
  1266. if Length(aValue) > 0 then
  1267. arrdata := @aValue[0]
  1268. else
  1269. arrdata := Nil;
  1270. TValue.MakeOpenArray(arrdata, Length(aValue), System.TypeInfo(aValue), Result);
  1271. end;
  1272. {$endif}
  1273. function TValue.GetIsEmpty: boolean;
  1274. begin
  1275. result := (FData.FTypeInfo=nil) or
  1276. ((Kind in [tkSString, tkObject, tkRecord, tkArray]) and not Assigned(FData.FValueData)) or
  1277. ((Kind in [tkClass, tkClassRef, tkInterfaceRaw]) and not Assigned(FData.FAsPointer));
  1278. end;
  1279. function TValue.IsArray: boolean;
  1280. begin
  1281. result := kind in [tkArray, tkDynArray];
  1282. end;
  1283. function TValue.IsOpenArray: Boolean;
  1284. var
  1285. td: PTypeData;
  1286. begin
  1287. td := TypeData;
  1288. Result := (Kind = tkArray) and (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0)
  1289. end;
  1290. function TValue.AsString: string;
  1291. begin
  1292. if System.GetTypeKind(String) = tkUString then
  1293. Result := String(AsUnicodeString)
  1294. else
  1295. Result := String(AsAnsiString);
  1296. end;
  1297. function TValue.AsUnicodeString: UnicodeString;
  1298. begin
  1299. if (Kind in [tkSString, tkAString, tkUString, tkWString]) and not Assigned(FData.FValueData) then
  1300. Result := ''
  1301. else
  1302. case Kind of
  1303. tkSString:
  1304. Result := UnicodeString(PShortString(FData.FValueData.GetReferenceToRawData)^);
  1305. tkAString:
  1306. Result := UnicodeString(PAnsiString(FData.FValueData.GetReferenceToRawData)^);
  1307. tkWString:
  1308. Result := UnicodeString(PWideString(FData.FValueData.GetReferenceToRawData)^);
  1309. tkUString:
  1310. Result := UnicodeString(PUnicodeString(FData.FValueData.GetReferenceToRawData)^);
  1311. else
  1312. raise EInvalidCast.Create(SErrInvalidTypecast);
  1313. end;
  1314. end;
  1315. function TValue.AsAnsiString: AnsiString;
  1316. begin
  1317. if (Kind in [tkSString, tkAString, tkUString, tkWString]) and not Assigned(FData.FValueData) then
  1318. Result := ''
  1319. else
  1320. case Kind of
  1321. tkSString:
  1322. Result := AnsiString(PShortString(FData.FValueData.GetReferenceToRawData)^);
  1323. tkAString:
  1324. Result := AnsiString(PAnsiString(FData.FValueData.GetReferenceToRawData)^);
  1325. tkWString:
  1326. Result := AnsiString(PWideString(FData.FValueData.GetReferenceToRawData)^);
  1327. tkUString:
  1328. Result := AnsiString(PUnicodeString(FData.FValueData.GetReferenceToRawData)^);
  1329. else
  1330. raise EInvalidCast.Create(SErrInvalidTypecast);
  1331. end;
  1332. end;
  1333. function TValue.AsExtended: Extended;
  1334. begin
  1335. if Kind = tkFloat then
  1336. begin
  1337. case TypeData^.FloatType of
  1338. ftSingle : result := FData.FAsSingle;
  1339. ftDouble : result := FData.FAsDouble;
  1340. ftExtended : result := FData.FAsExtended;
  1341. ftCurr : result := FData.FAsCurr;
  1342. ftComp : result := FData.FAsComp;
  1343. else
  1344. raise EInvalidCast.Create(SErrInvalidTypecast);
  1345. end;
  1346. end
  1347. else
  1348. raise EInvalidCast.Create(SErrInvalidTypecast);
  1349. end;
  1350. function TValue.IsObject: boolean;
  1351. begin
  1352. result := (Kind = tkClass) or ((Kind = tkUnknown) and not Assigned(FData.FAsObject));
  1353. end;
  1354. function TValue.IsClass: boolean;
  1355. begin
  1356. result := (Kind = tkClassRef) or ((Kind in [tkClass,tkUnknown]) and not Assigned(FData.FAsObject));
  1357. end;
  1358. function TValue.IsOrdinal: boolean;
  1359. begin
  1360. result := (Kind in [tkInteger, tkInt64, tkQWord, tkBool]) or
  1361. ((Kind in [tkClass, tkClassRef, tkInterfaceRaw, tkUnknown]) and not Assigned(FData.FAsPointer));
  1362. end;
  1363. function TValue.IsType(ATypeInfo: PTypeInfo): boolean;
  1364. begin
  1365. result := ATypeInfo = TypeInfo;
  1366. end;
  1367. function TValue.AsObject: TObject;
  1368. begin
  1369. if IsObject or (IsClass and not Assigned(FData.FAsObject)) then
  1370. result := TObject(FData.FAsObject)
  1371. else
  1372. raise EInvalidCast.Create(SErrInvalidTypecast);
  1373. end;
  1374. function TValue.AsClass: TClass;
  1375. begin
  1376. if IsClass then
  1377. result := FData.FAsClass
  1378. else
  1379. raise EInvalidCast.Create(SErrInvalidTypecast);
  1380. end;
  1381. function TValue.AsBoolean: boolean;
  1382. begin
  1383. if (Kind = tkBool) then
  1384. case TypeData^.OrdType of
  1385. otSByte: Result := ByteBool(FData.FAsSByte);
  1386. otUByte: Result := Boolean(FData.FAsUByte);
  1387. otSWord: Result := WordBool(FData.FAsSWord);
  1388. otUWord: Result := Boolean16(FData.FAsUWord);
  1389. otSLong: Result := LongBool(FData.FAsSLong);
  1390. otULong: Result := Boolean32(FData.FAsULong);
  1391. otSQWord: Result := QWordBool(FData.FAsSInt64);
  1392. otUQWord: Result := Boolean64(FData.FAsUInt64);
  1393. end
  1394. else
  1395. raise EInvalidCast.Create(SErrInvalidTypecast);
  1396. end;
  1397. function TValue.AsOrdinal: Int64;
  1398. begin
  1399. if IsOrdinal then
  1400. if Kind in [tkClass, tkClassRef, tkInterfaceRaw, tkUnknown] then
  1401. Result := 0
  1402. else
  1403. case TypeData^.OrdType of
  1404. otSByte: Result := FData.FAsSByte;
  1405. otUByte: Result := FData.FAsUByte;
  1406. otSWord: Result := FData.FAsSWord;
  1407. otUWord: Result := FData.FAsUWord;
  1408. otSLong: Result := FData.FAsSLong;
  1409. otULong: Result := FData.FAsULong;
  1410. otSQWord: Result := FData.FAsSInt64;
  1411. otUQWord: Result := FData.FAsUInt64;
  1412. end
  1413. else
  1414. raise EInvalidCast.Create(SErrInvalidTypecast);
  1415. end;
  1416. function TValue.AsCurrency: Currency;
  1417. begin
  1418. if (Kind = tkFloat) and (TypeData^.FloatType=ftCurr) then
  1419. result := FData.FAsCurr
  1420. else
  1421. raise EInvalidCast.Create(SErrInvalidTypecast);
  1422. end;
  1423. function TValue.AsInteger: Integer;
  1424. begin
  1425. if Kind in [tkInteger, tkInt64, tkQWord] then
  1426. case TypeData^.OrdType of
  1427. otSByte: Result := FData.FAsSByte;
  1428. otUByte: Result := FData.FAsUByte;
  1429. otSWord: Result := FData.FAsSWord;
  1430. otUWord: Result := FData.FAsUWord;
  1431. otSLong: Result := FData.FAsSLong;
  1432. otULong: Result := FData.FAsULong;
  1433. otSQWord: Result := FData.FAsSInt64;
  1434. otUQWord: Result := FData.FAsUInt64;
  1435. end
  1436. else
  1437. raise EInvalidCast.Create(SErrInvalidTypecast);
  1438. end;
  1439. function TValue.AsInt64: Int64;
  1440. begin
  1441. if Kind in [tkInteger, tkInt64, tkQWord] then
  1442. case TypeData^.OrdType of
  1443. otSByte: Result := FData.FAsSByte;
  1444. otUByte: Result := FData.FAsUByte;
  1445. otSWord: Result := FData.FAsSWord;
  1446. otUWord: Result := FData.FAsUWord;
  1447. otSLong: Result := FData.FAsSLong;
  1448. otULong: Result := FData.FAsULong;
  1449. otSQWord: Result := FData.FAsSInt64;
  1450. otUQWord: Result := FData.FAsUInt64;
  1451. end
  1452. else if (Kind = tkFloat) and (TypeData^.FloatType = ftComp) then
  1453. Result := Int64(FData.FAsComp)
  1454. else
  1455. raise EInvalidCast.Create(SErrInvalidTypecast);
  1456. end;
  1457. function TValue.AsUInt64: QWord;
  1458. begin
  1459. if Kind in [tkInteger, tkInt64, tkQWord] then
  1460. case TypeData^.OrdType of
  1461. otSByte: Result := FData.FAsSByte;
  1462. otUByte: Result := FData.FAsUByte;
  1463. otSWord: Result := FData.FAsSWord;
  1464. otUWord: Result := FData.FAsUWord;
  1465. otSLong: Result := FData.FAsSLong;
  1466. otULong: Result := FData.FAsULong;
  1467. otSQWord: Result := FData.FAsSInt64;
  1468. otUQWord: Result := FData.FAsUInt64;
  1469. end
  1470. else if (Kind = tkFloat) and (TypeData^.FloatType = ftComp) then
  1471. Result := QWord(FData.FAsComp)
  1472. else
  1473. raise EInvalidCast.Create(SErrInvalidTypecast);
  1474. end;
  1475. function TValue.AsInterface: IInterface;
  1476. begin
  1477. if Kind = tkInterface then
  1478. Result := PInterface(FData.FValueData.GetReferenceToRawData)^
  1479. else if (Kind in [tkClass, tkClassRef, tkUnknown]) and not Assigned(FData.FAsPointer) then
  1480. Result := Nil
  1481. else
  1482. raise EInvalidCast.Create(SErrInvalidTypecast);
  1483. end;
  1484. function TValue.ToString: String;
  1485. begin
  1486. case Kind of
  1487. tkWString,
  1488. tkUString : result := AsUnicodeString;
  1489. tkSString,
  1490. tkAString : result := AsAnsiString;
  1491. tkInteger : result := IntToStr(AsInteger);
  1492. tkQWord : result := IntToStr(AsUInt64);
  1493. tkInt64 : result := IntToStr(AsInt64);
  1494. tkBool : result := BoolToStr(AsBoolean, True);
  1495. else
  1496. result := '';
  1497. end;
  1498. end;
  1499. function TValue.GetArrayLength: SizeInt;
  1500. var
  1501. td: PTypeData;
  1502. begin
  1503. if not IsArray then
  1504. raise EInvalidCast.Create(SErrInvalidTypecast);
  1505. if Kind = tkDynArray then
  1506. Result := DynArraySize(PPointer(FData.FValueData.GetReferenceToRawData)^)
  1507. else begin
  1508. td := TypeData;
  1509. if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then
  1510. Result := FData.FArrLength
  1511. else
  1512. Result := td^.ArrayData.ElCount;
  1513. end;
  1514. end;
  1515. function TValue.GetArrayElement(AIndex: SizeInt): TValue;
  1516. var
  1517. data: Pointer;
  1518. eltype: PTypeInfo;
  1519. elsize: SizeInt;
  1520. td: PTypeData;
  1521. begin
  1522. if not IsArray then
  1523. raise EInvalidCast.Create(SErrInvalidTypecast);
  1524. if Kind = tkDynArray then begin
  1525. data := DynArrayIndex(PPointer(FData.FValueData.GetReferenceToRawData)^, [AIndex], FData.FTypeInfo);
  1526. eltype := TypeData^.elType2;
  1527. end else begin
  1528. td := TypeData;
  1529. eltype := td^.ArrayData.ElType;
  1530. { open array? }
  1531. if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then begin
  1532. data := PPointer(FData.FValueData.GetReferenceToRawData)^;
  1533. elsize := FData.FElSize
  1534. end else begin
  1535. data := FData.FValueData.GetReferenceToRawData;
  1536. elsize := td^.ArrayData.Size div td^.ArrayData.ElCount;
  1537. end;
  1538. data := PByte(data) + AIndex * elsize;
  1539. end;
  1540. { MakeWithoutCopy? }
  1541. Make(data, eltype, Result);
  1542. end;
  1543. procedure TValue.SetArrayElement(AIndex: SizeInt; constref AValue: TValue);
  1544. var
  1545. data: Pointer;
  1546. eltype: PTypeInfo;
  1547. elsize: SizeInt;
  1548. td, tdv: PTypeData;
  1549. begin
  1550. if not IsArray then
  1551. raise EInvalidCast.Create(SErrInvalidTypecast);
  1552. if Kind = tkDynArray then begin
  1553. data := DynArrayIndex(PPointer(FData.FValueData.GetReferenceToRawData)^, [AIndex], FData.FTypeInfo);
  1554. eltype := TypeData^.elType2;
  1555. end else begin
  1556. td := TypeData;
  1557. eltype := td^.ArrayData.ElType;
  1558. { open array? }
  1559. if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then begin
  1560. data := PPointer(FData.FValueData.GetReferenceToRawData)^;
  1561. elsize := FData.FElSize
  1562. end else begin
  1563. data := FData.FValueData.GetReferenceToRawData;
  1564. elsize := td^.ArrayData.Size div td^.ArrayData.ElCount;
  1565. end;
  1566. data := PByte(data) + AIndex * elsize;
  1567. end;
  1568. { maybe we'll later on allow some typecasts, but for now be restrictive }
  1569. if eltype^.Kind <> AValue.Kind then
  1570. raise EInvalidCast.Create(SErrInvalidTypecast);
  1571. td := GetTypeData(eltype);
  1572. tdv := AValue.TypeData;
  1573. if ((eltype^.Kind in [tkInteger, tkBool, tkEnumeration, tkSet]) and (td^.OrdType <> tdv^.OrdType)) or
  1574. ((eltype^.Kind = tkFloat) and (td^.FloatType <> tdv^.FloatType)) then
  1575. raise EInvalidCast.Create(SErrInvalidTypecast);
  1576. if Assigned(AValue.FData.FValueData) and (eltype^.Kind <> tkSString) then
  1577. IntCopy(AValue.FData.FValueData.GetReferenceToRawData, data, eltype)
  1578. else
  1579. Move(AValue.GetReferenceToRawData^, data^, AValue.DataSize);
  1580. end;
  1581. function TValue.TryAsOrdinal(out AResult: int64): boolean;
  1582. begin
  1583. result := IsOrdinal;
  1584. if result then
  1585. AResult := AsOrdinal;
  1586. end;
  1587. function TValue.GetReferenceToRawData: Pointer;
  1588. begin
  1589. if not Assigned(FData.FTypeInfo) then
  1590. Result := Nil
  1591. else if Assigned(FData.FValueData) then
  1592. Result := FData.FValueData.GetReferenceToRawData
  1593. else begin
  1594. Result := Nil;
  1595. case Kind of
  1596. tkInteger,
  1597. tkEnumeration,
  1598. tkInt64,
  1599. tkQWord,
  1600. tkBool:
  1601. case TypeData^.OrdType of
  1602. otSByte:
  1603. Result := @FData.FAsSByte;
  1604. otUByte:
  1605. Result := @FData.FAsUByte;
  1606. otSWord:
  1607. Result := @FData.FAsSWord;
  1608. otUWord:
  1609. Result := @FData.FAsUWord;
  1610. otSLong:
  1611. Result := @FData.FAsSLong;
  1612. otULong:
  1613. Result := @FData.FAsULong;
  1614. otSQWord:
  1615. Result := @FData.FAsSInt64;
  1616. otUQWord:
  1617. Result := @FData.FAsUInt64;
  1618. end;
  1619. tkSet: begin
  1620. case TypeData^.OrdType of
  1621. otUByte: begin
  1622. case TypeData^.SetSize of
  1623. 1:
  1624. Result := @FData.FAsUByte;
  1625. 2:
  1626. Result := @FData.FAsUWord;
  1627. 3, 4:
  1628. Result := @FData.FAsULong;
  1629. 5..8:
  1630. Result := @FData.FAsUInt64;
  1631. else
  1632. { this should have gone through FAsValueData :/ }
  1633. Result := Nil;
  1634. end;
  1635. end;
  1636. otUWord:
  1637. Result := @FData.FAsUWord;
  1638. otULong:
  1639. Result := @FData.FAsULong;
  1640. else
  1641. Result := Nil;
  1642. end;
  1643. end;
  1644. tkChar:
  1645. Result := @FData.FAsUByte;
  1646. tkFloat:
  1647. case TypeData^.FloatType of
  1648. ftSingle:
  1649. Result := @FData.FAsSingle;
  1650. ftDouble:
  1651. Result := @FData.FAsDouble;
  1652. ftExtended:
  1653. Result := @FData.FAsExtended;
  1654. ftComp:
  1655. Result := @FData.FAsComp;
  1656. ftCurr:
  1657. Result := @FData.FAsCurr;
  1658. end;
  1659. tkMethod:
  1660. Result := @FData.FAsMethod;
  1661. tkClass:
  1662. Result := @FData.FAsObject;
  1663. tkWChar:
  1664. Result := @FData.FAsUWord;
  1665. tkInterfaceRaw:
  1666. Result := @FData.FAsPointer;
  1667. tkProcVar:
  1668. Result := @FData.FAsMethod.Code;
  1669. tkUChar:
  1670. Result := @FData.FAsUWord;
  1671. tkFile:
  1672. Result := @FData.FAsPointer;
  1673. tkClassRef:
  1674. Result := @FData.FAsClass;
  1675. tkPointer:
  1676. Result := @FData.FAsPointer;
  1677. tkVariant,
  1678. tkDynArray,
  1679. tkArray,
  1680. tkObject,
  1681. tkRecord,
  1682. tkInterface,
  1683. tkSString,
  1684. tkLString,
  1685. tkAString,
  1686. tkUString,
  1687. tkWString:
  1688. Assert(false, 'Managed/complex type not handled through IValueData');
  1689. end;
  1690. end;
  1691. end;
  1692. procedure TValue.ExtractRawData(ABuffer: Pointer);
  1693. begin
  1694. if Assigned(FData.FValueData) then
  1695. FData.FValueData.ExtractRawData(ABuffer)
  1696. else if Assigned(FData.FTypeInfo) then
  1697. Move((@FData.FAsPointer)^, ABuffer^, DataSize);
  1698. end;
  1699. procedure TValue.ExtractRawDataNoCopy(ABuffer: Pointer);
  1700. begin
  1701. if Assigned(FData.FValueData) then
  1702. FData.FValueData.ExtractRawDataNoCopy(ABuffer)
  1703. else if Assigned(FData.FTypeInfo) then
  1704. Move((@FData.FAsPointer)^, ABuffer^, DataSize);
  1705. end;
  1706. class operator TValue.:=(const AValue: String): TValue;
  1707. begin
  1708. Make(@AValue, System.TypeInfo(AValue), Result);
  1709. end;
  1710. class operator TValue.:=(AValue: LongInt): TValue;
  1711. begin
  1712. Make(@AValue, System.TypeInfo(AValue), Result);
  1713. end;
  1714. class operator TValue.:=(AValue: Single): TValue;
  1715. begin
  1716. Make(@AValue, System.TypeInfo(AValue), Result);
  1717. end;
  1718. class operator TValue.:=(AValue: Double): TValue;
  1719. begin
  1720. Make(@AValue, System.TypeInfo(AValue), Result);
  1721. end;
  1722. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1723. class operator TValue.:=(AValue: Extended): TValue;
  1724. begin
  1725. Make(@AValue, System.TypeInfo(AValue), Result);
  1726. end;
  1727. {$endif}
  1728. class operator TValue.:=(AValue: Currency): TValue;
  1729. begin
  1730. Make(@AValue, System.TypeInfo(AValue), Result);
  1731. end;
  1732. class operator TValue.:=(AValue: Int64): TValue;
  1733. begin
  1734. Make(@AValue, System.TypeInfo(AValue), Result);
  1735. end;
  1736. class operator TValue.:=(AValue: QWord): TValue;
  1737. begin
  1738. Make(@AValue, System.TypeInfo(AValue), Result);
  1739. end;
  1740. class operator TValue.:=(AValue: TObject): TValue;
  1741. begin
  1742. Make(@AValue, System.TypeInfo(AValue), Result);
  1743. end;
  1744. class operator TValue.:=(AValue: TClass): TValue;
  1745. begin
  1746. Make(@AValue, System.TypeInfo(AValue), Result);
  1747. end;
  1748. class operator TValue.:=(AValue: Boolean): TValue;
  1749. begin
  1750. Make(@AValue, System.TypeInfo(AValue), Result);
  1751. end;
  1752. function Invoke(aCodeAddress: CodePointer; const aArgs: TValueArray;
  1753. aCallConv: TCallConv; aResultType: PTypeInfo; aIsStatic: Boolean;
  1754. aIsConstructor: Boolean): TValue;
  1755. var
  1756. funcargs: TFunctionCallParameterArray;
  1757. i: LongInt;
  1758. flags: TFunctionCallFlags;
  1759. begin
  1760. { sanity check }
  1761. if not Assigned(FuncCallMgr[aCallConv].Invoke) then
  1762. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  1763. { ToDo: handle IsConstructor }
  1764. if aIsConstructor then
  1765. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  1766. flags := [];
  1767. if aIsStatic then
  1768. Include(flags, fcfStatic)
  1769. else if Length(aArgs) = 0 then
  1770. raise EInvocationError.Create(SErrMissingSelfParam);
  1771. SetLength(funcargs, Length(aArgs));
  1772. for i := Low(aArgs) to High(aArgs) do begin
  1773. funcargs[i - Low(aArgs) + Low(funcargs)].ValueRef := aArgs[i].GetReferenceToRawData;
  1774. funcargs[i - Low(aArgs) + Low(funcargs)].ValueSize := aArgs[i].DataSize;
  1775. funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParamType := aArgs[i].TypeInfo;
  1776. funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParamFlags := [];
  1777. funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParaLocs := Nil;
  1778. end;
  1779. if Assigned(aResultType) then
  1780. TValue.Make(Nil, aResultType, Result)
  1781. else
  1782. Result := TValue.Empty;
  1783. FuncCallMgr[aCallConv].Invoke(aCodeAddress, funcargs, aCallConv, aResultType, Result.GetReferenceToRawData, flags);
  1784. end;
  1785. 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;
  1786. var
  1787. arrparam, param: TRttiParameter;
  1788. unhidden, highs, i: SizeInt;
  1789. args: TFunctionCallParameterArray;
  1790. highargs: array of SizeInt;
  1791. restype: PTypeInfo;
  1792. resptr: Pointer;
  1793. mgr: TFunctionCallManager;
  1794. flags: TFunctionCallFlags;
  1795. begin
  1796. mgr := FuncCallMgr[aCallConv];
  1797. if not Assigned(mgr.Invoke) then
  1798. raise EInvocationError.CreateFmt(SErrCallConvNotSupported, [CCToStr(aCallConv)]);
  1799. if not Assigned(aCodeAddress) then
  1800. raise EInvocationError.CreateFmt(SErrInvokeNoCodeAddr, [aName]);
  1801. unhidden := 0;
  1802. highs := 0;
  1803. for param in aParams do begin
  1804. if unhidden < Length(aArgs) then begin
  1805. if pfArray in param.Flags then begin
  1806. if Assigned(aArgs[unhidden].TypeInfo) and not aArgs[unhidden].IsArray and (aArgs[unhidden].Kind <> param.ParamType.TypeKind) then
  1807. raise EInvocationError.CreateFmt(SErrInvokeArrayArgExpected, [param.Name, aName]);
  1808. end else if not (pfHidden in param.Flags) then begin
  1809. if Assigned(param.ParamType) and (aArgs[unhidden].Kind <> param.ParamType.TypeKind) then
  1810. raise EInvocationError.CreateFmt(SErrInvokeArgInvalidType, [param.Name, aName]);
  1811. end;
  1812. end;
  1813. if not (pfHidden in param.Flags) then
  1814. Inc(unhidden);
  1815. if pfHigh in param.Flags then
  1816. Inc(highs);
  1817. end;
  1818. if unhidden <> Length(aArgs) then
  1819. raise EInvocationError.CreateFmt(SErrInvokeArgCount, [aName, unhidden, Length(aArgs)]);
  1820. if Assigned(aReturnType) then begin
  1821. TValue.Make(Nil, aReturnType.FTypeInfo, Result);
  1822. resptr := Result.GetReferenceToRawData;
  1823. restype := aReturnType.FTypeInfo;
  1824. end else begin
  1825. Result := TValue.Empty;
  1826. resptr := Nil;
  1827. restype := Nil;
  1828. end;
  1829. SetLength(highargs, highs);
  1830. SetLength(args, Length(aParams));
  1831. unhidden := 0;
  1832. highs := 0;
  1833. for i := 0 to High(aParams) do begin
  1834. param := aParams[i];
  1835. if Assigned(param.ParamType) then
  1836. args[i].Info.ParamType := param.ParamType.FTypeInfo
  1837. else
  1838. args[i].Info.ParamType := Nil;
  1839. args[i].Info.ParamFlags := param.Flags;
  1840. args[i].Info.ParaLocs := Nil;
  1841. if pfHidden in param.Flags then begin
  1842. if pfSelf in param.Flags then
  1843. args[i].ValueRef := aInstance.GetReferenceToRawData
  1844. else if pfResult in param.Flags then begin
  1845. if not Assigned(restype) then
  1846. raise EInvocationError.CreateFmt(SErrInvokeRttiDataError, [aName]);
  1847. args[i].ValueRef := resptr;
  1848. restype := Nil;
  1849. resptr := Nil;
  1850. end else if pfHigh in param.Flags then begin
  1851. { the corresponding array argument is the *previous* unhidden argument }
  1852. if aArgs[unhidden - 1].IsArray then
  1853. highargs[highs] := aArgs[unhidden - 1].GetArrayLength - 1
  1854. else if not Assigned(aArgs[unhidden - 1].TypeInfo) then
  1855. highargs[highs] := -1
  1856. else
  1857. highargs[highs] := 0;
  1858. args[i].ValueRef := @highargs[highs];
  1859. Inc(highs);
  1860. end;
  1861. end else begin
  1862. if (pfArray in param.Flags) then begin
  1863. if not Assigned(aArgs[unhidden].TypeInfo) then
  1864. args[i].ValueRef := Nil
  1865. else if aArgs[unhidden].Kind = tkDynArray then
  1866. args[i].ValueRef := PPointer(aArgs[unhidden].GetReferenceToRawData)^
  1867. else
  1868. args[i].ValueRef := aArgs[unhidden].GetReferenceToRawData;
  1869. end else
  1870. args[i].ValueRef := aArgs[unhidden].GetReferenceToRawData;
  1871. Inc(unhidden);
  1872. end;
  1873. end;
  1874. flags := [];
  1875. if aStatic then
  1876. Include(flags, fcfStatic);
  1877. mgr.Invoke(aCodeAddress, args, aCallConv, restype, resptr, flags);
  1878. end;
  1879. function CreateCallbackProc(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  1880. begin
  1881. if not Assigned(FuncCallMgr[aCallConv].CreateCallbackProc) then
  1882. raise ENotImplemented.Create(SErrCallbackNotImplented);
  1883. if not Assigned(aHandler) then
  1884. raise EArgumentNilException.Create(SErrCallbackHandlerNil);
  1885. Result := FuncCallMgr[aCallConv].CreateCallbackProc(aHandler, aCallConv, aArgs, aResultType, aFlags, aContext);
  1886. end;
  1887. function CreateCallbackMethod(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  1888. begin
  1889. if not Assigned(FuncCallMgr[aCallConv].CreateCallbackMethod) then
  1890. raise ENotImplemented.Create(SErrCallbackNotImplented);
  1891. if not Assigned(aHandler) then
  1892. raise EArgumentNilException.Create(SErrCallbackHandlerNil);
  1893. Result := FuncCallMgr[aCallConv].CreateCallbackMethod(aHandler, aCallConv, aArgs, aResultType, aFlags, aContext);
  1894. end;
  1895. function IsManaged(TypeInfo: PTypeInfo): boolean;
  1896. begin
  1897. if Assigned(TypeInfo) then
  1898. case TypeInfo^.Kind of
  1899. tkAString,
  1900. tkLString,
  1901. tkWString,
  1902. tkUString,
  1903. tkInterface,
  1904. tkVariant,
  1905. tkDynArray : Result := true;
  1906. tkArray : Result := IsManaged(GetTypeData(TypeInfo)^.ArrayData.ElType);
  1907. tkRecord,
  1908. tkObject :
  1909. with GetTypeData(TypeInfo)^.RecInitData^ do
  1910. Result := (ManagedFieldCount > 0) or Assigned(ManagementOp);
  1911. else
  1912. Result := false;
  1913. end
  1914. else
  1915. Result := false;
  1916. end;
  1917. {$ifndef InLazIDE}
  1918. generic function OpenArrayToDynArrayValue<T>(constref aArray: array of T): TValue;
  1919. var
  1920. arr: specialize TArray<T>;
  1921. i: SizeInt;
  1922. begin
  1923. SetLength(arr, Length(aArray));
  1924. for i := 0 to High(aArray) do
  1925. arr[i] := aArray[i];
  1926. Result := TValue.specialize From<specialize TArray<T>>(arr);
  1927. end;
  1928. {$endif}
  1929. { TRttiPointerType }
  1930. function TRttiPointerType.GetReferredType: TRttiType;
  1931. begin
  1932. Result := GRttiPool.GetType(FTypeData^.RefType);
  1933. end;
  1934. { TRttiRefCountedInterfaceType }
  1935. function TRttiRefCountedInterfaceType.IntfData: PInterfaceData;
  1936. begin
  1937. Result := PInterfaceData(FTypeData);
  1938. end;
  1939. function TRttiRefCountedInterfaceType.MethodTable: PIntfMethodTable;
  1940. begin
  1941. Result := IntfData^.MethodTable;
  1942. end;
  1943. function TRttiRefCountedInterfaceType.GetIntfBaseType: TRttiInterfaceType;
  1944. var
  1945. context: TRttiContext;
  1946. begin
  1947. if not Assigned(IntfData^.Parent) then
  1948. Exit(Nil);
  1949. context := TRttiContext.Create;
  1950. try
  1951. Result := context.GetType(IntfData^.Parent^) as TRttiInterfaceType;
  1952. finally
  1953. context.Free;
  1954. end;
  1955. end;
  1956. function TRttiRefCountedInterfaceType.GetDeclaringUnitName: String;
  1957. begin
  1958. Result := IntfData^.UnitName;
  1959. end;
  1960. function TRttiRefCountedInterfaceType.GetGUID: TGUID;
  1961. begin
  1962. Result := IntfData^.GUID;
  1963. end;
  1964. function TRttiRefCountedInterfaceType.GetIntfFlags: TIntfFlags;
  1965. begin
  1966. Result := IntfData^.Flags;
  1967. end;
  1968. function TRttiRefCountedInterfaceType.GetIntfType: TInterfaceType;
  1969. begin
  1970. Result := itRefCounted;
  1971. end;
  1972. { TRttiRawInterfaceType }
  1973. function TRttiRawInterfaceType.IntfData: PInterfaceRawData;
  1974. begin
  1975. Result := PInterfaceRawData(FTypeData);
  1976. end;
  1977. function TRttiRawInterfaceType.MethodTable: PIntfMethodTable;
  1978. begin
  1979. { currently there is none! }
  1980. Result := Nil;
  1981. end;
  1982. function TRttiRawInterfaceType.GetIntfBaseType: TRttiInterfaceType;
  1983. var
  1984. context: TRttiContext;
  1985. begin
  1986. if not Assigned(IntfData^.Parent) then
  1987. Exit(Nil);
  1988. context := TRttiContext.Create;
  1989. try
  1990. Result := context.GetType(IntfData^.Parent^) as TRttiInterfaceType;
  1991. finally
  1992. context.Free;
  1993. end;
  1994. end;
  1995. function TRttiRawInterfaceType.GetDeclaringUnitName: String;
  1996. begin
  1997. Result := IntfData^.UnitName;
  1998. end;
  1999. function TRttiRawInterfaceType.GetGUID: TGUID;
  2000. begin
  2001. Result := IntfData^.IID;
  2002. end;
  2003. function TRttiRawInterfaceType.GetGUIDStr: String;
  2004. begin
  2005. Result := IntfData^.IIDStr;
  2006. end;
  2007. function TRttiRawInterfaceType.GetIntfFlags: TIntfFlags;
  2008. begin
  2009. Result := IntfData^.Flags;
  2010. end;
  2011. function TRttiRawInterfaceType.GetIntfType: TInterfaceType;
  2012. begin
  2013. Result := itRaw;
  2014. end;
  2015. { TRttiVmtMethodParameter }
  2016. function TRttiVmtMethodParameter.GetHandle: Pointer;
  2017. begin
  2018. Result := FVmtMethodParam;
  2019. end;
  2020. function TRttiVmtMethodParameter.GetName: String;
  2021. begin
  2022. Result := FVmtMethodParam^.Name;
  2023. end;
  2024. function TRttiVmtMethodParameter.GetFlags: TParamFlags;
  2025. begin
  2026. Result := FVmtMethodParam^.Flags;
  2027. end;
  2028. function TRttiVmtMethodParameter.GetParamType: TRttiType;
  2029. var
  2030. context: TRttiContext;
  2031. begin
  2032. if not Assigned(FVmtMethodParam^.ParamType) then
  2033. Exit(Nil);
  2034. context := TRttiContext.Create;
  2035. try
  2036. Result := context.GetType(FVmtMethodParam^.ParamType^);
  2037. finally
  2038. context.Free;
  2039. end;
  2040. end;
  2041. constructor TRttiVmtMethodParameter.Create(AVmtMethodParam: PVmtMethodParam);
  2042. begin
  2043. inherited Create;
  2044. FVmtMethodParam := AVmtMethodParam;
  2045. end;
  2046. { TRttiMethodTypeParameter }
  2047. function TRttiMethodTypeParameter.GetHandle: Pointer;
  2048. begin
  2049. Result := fHandle;
  2050. end;
  2051. function TRttiMethodTypeParameter.GetName: String;
  2052. begin
  2053. Result := fName;
  2054. end;
  2055. function TRttiMethodTypeParameter.GetFlags: TParamFlags;
  2056. begin
  2057. Result := fFlags;
  2058. end;
  2059. function TRttiMethodTypeParameter.GetParamType: TRttiType;
  2060. var
  2061. context: TRttiContext;
  2062. begin
  2063. context := TRttiContext.Create;
  2064. try
  2065. Result := context.GetType(FType);
  2066. finally
  2067. context.Free;
  2068. end;
  2069. end;
  2070. constructor TRttiMethodTypeParameter.Create(aHandle: Pointer; const aName: String; aFlags: TParamFlags; aType: PTypeInfo);
  2071. begin
  2072. fHandle := aHandle;
  2073. fName := aName;
  2074. fFlags := aFlags;
  2075. fType := aType;
  2076. end;
  2077. { TRttiIntfMethod }
  2078. function TRttiIntfMethod.GetHandle: Pointer;
  2079. begin
  2080. Result := FIntfMethodEntry;
  2081. end;
  2082. function TRttiIntfMethod.GetName: String;
  2083. begin
  2084. Result := FIntfMethodEntry^.Name;
  2085. end;
  2086. function TRttiIntfMethod.GetCallingConvention: TCallConv;
  2087. begin
  2088. Result := FIntfMethodEntry^.CC;
  2089. end;
  2090. function TRttiIntfMethod.GetCodeAddress: CodePointer;
  2091. begin
  2092. Result := Nil;
  2093. end;
  2094. function TRttiIntfMethod.GetDispatchKind: TDispatchKind;
  2095. begin
  2096. Result := dkInterface;
  2097. end;
  2098. function TRttiIntfMethod.GetHasExtendedInfo: Boolean;
  2099. begin
  2100. Result := True;
  2101. end;
  2102. function TRttiIntfMethod.GetIsClassMethod: Boolean;
  2103. begin
  2104. Result := False;
  2105. end;
  2106. function TRttiIntfMethod.GetIsConstructor: Boolean;
  2107. begin
  2108. Result := False;
  2109. end;
  2110. function TRttiIntfMethod.GetIsDestructor: Boolean;
  2111. begin
  2112. Result := False;
  2113. end;
  2114. function TRttiIntfMethod.GetIsStatic: Boolean;
  2115. begin
  2116. Result := False;
  2117. end;
  2118. function TRttiIntfMethod.GetMethodKind: TMethodKind;
  2119. begin
  2120. Result := FIntfMethodEntry^.Kind;
  2121. end;
  2122. function TRttiIntfMethod.GetReturnType: TRttiType;
  2123. var
  2124. context: TRttiContext;
  2125. begin
  2126. if not Assigned(FIntfMethodEntry^.ResultType) then
  2127. Exit(Nil);
  2128. context := TRttiContext.Create;
  2129. try
  2130. Result := context.GetType(FIntfMethodEntry^.ResultType^);
  2131. finally
  2132. context.Free;
  2133. end;
  2134. end;
  2135. function TRttiIntfMethod.GetVirtualIndex: SmallInt;
  2136. begin
  2137. Result := FIndex;
  2138. end;
  2139. constructor TRttiIntfMethod.Create(AParent: TRttiType; AIntfMethodEntry: PIntfMethodEntry; AIndex: SmallInt);
  2140. begin
  2141. inherited Create(AParent);
  2142. FIntfMethodEntry := AIntfMethodEntry;
  2143. FIndex := AIndex;
  2144. end;
  2145. function TRttiIntfMethod.GetParameters(aWithHidden: Boolean): specialize TArray<TRttiParameter>;
  2146. var
  2147. param: PVmtMethodParam;
  2148. total, visible: SizeInt;
  2149. context: TRttiContext;
  2150. obj: TRttiObject;
  2151. begin
  2152. if aWithHidden and (Length(FParamsAll) > 0) then
  2153. Exit(FParamsAll);
  2154. if not aWithHidden and (Length(FParams) > 0) then
  2155. Exit(FParams);
  2156. if FIntfMethodEntry^.ParamCount = 0 then
  2157. Exit(Nil);
  2158. SetLength(FParams, FIntfMethodEntry^.ParamCount);
  2159. SetLength(FParamsAll, FIntfMethodEntry^.ParamCount);
  2160. context := TRttiContext.Create;
  2161. try
  2162. total := 0;
  2163. visible := 0;
  2164. param := FIntfMethodEntry^.Param[0];
  2165. while total < FIntfMethodEntry^.ParamCount do begin
  2166. obj := context.GetByHandle(param);
  2167. if Assigned(obj) then
  2168. FParamsAll[total] := obj as TRttiVmtMethodParameter
  2169. else begin
  2170. FParamsAll[total] := TRttiVmtMethodParameter.Create(param);
  2171. context.AddObject(FParamsAll[total]);
  2172. end;
  2173. if not (pfHidden in param^.Flags) then begin
  2174. FParams[visible] := FParamsAll[total];
  2175. Inc(visible);
  2176. end;
  2177. param := param^.Next;
  2178. Inc(total);
  2179. end;
  2180. if visible <> total then
  2181. SetLength(FParams, visible);
  2182. finally
  2183. context.Free;
  2184. end;
  2185. if aWithHidden then
  2186. Result := FParamsAll
  2187. else
  2188. Result := FParams;
  2189. end;
  2190. { TRttiFloatType }
  2191. function TRttiFloatType.GetFloatType: TFloatType;
  2192. begin
  2193. result := FTypeData^.FloatType;
  2194. end;
  2195. { TRttiParameter }
  2196. function TRttiParameter.ToString: String;
  2197. var
  2198. f: TParamFlags;
  2199. n: String;
  2200. t: TRttiType;
  2201. begin
  2202. if FString = '' then begin
  2203. f := Flags;
  2204. if pfVar in f then
  2205. FString := 'var'
  2206. else if pfConst in f then
  2207. FString := 'const'
  2208. else if pfOut in f then
  2209. FString := 'out'
  2210. else if pfConstRef in f then
  2211. FString := 'constref';
  2212. if FString <> '' then
  2213. FString := FString + ' ';
  2214. n := Name;
  2215. if n = '' then
  2216. n := '<unknown>';
  2217. FString := FString + n;
  2218. t := ParamType;
  2219. if Assigned(t) then begin
  2220. FString := FString + ': ';
  2221. if pfArray in flags then
  2222. FString := 'array of ';
  2223. FString := FString + t.Name;
  2224. end;
  2225. end;
  2226. Result := FString;
  2227. end;
  2228. { TMethodImplementation }
  2229. function TMethodImplementation.GetCodeAddress: CodePointer;
  2230. begin
  2231. Result := fLowLevelCallback.CodeAddress;
  2232. end;
  2233. procedure TMethodImplementation.InitArgs;
  2234. var
  2235. i, refargs: SizeInt;
  2236. begin
  2237. i := 0;
  2238. refargs := 0;
  2239. SetLength(fRefArgs, Length(fArgs));
  2240. while i < Length(fArgs) do begin
  2241. if (fArgs[i].ParamFlags * [pfVar, pfOut] <> []) and not (pfHidden in fArgs[i].ParamFlags) then begin
  2242. fRefArgs[refargs] := fArgLen;
  2243. Inc(refargs);
  2244. end;
  2245. if pfArray in fArgs[i].ParamFlags then begin
  2246. Inc(i);
  2247. if (i = Length(fArgs)) or not (pfHigh in fArgs[i].ParamFlags) then
  2248. raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
  2249. Inc(fArgLen);
  2250. end else if not (pfHidden in fArgs[i].ParamFlags) or (pfSelf in fArgs[i].ParamFlags) then
  2251. Inc(fArgLen)
  2252. else if (pfResult in fArgs[i].ParamFlags) then
  2253. fResult := fArgs[i].ParamType;
  2254. Inc(i);
  2255. end;
  2256. SetLength(fRefArgs, refargs);
  2257. end;
  2258. procedure TMethodImplementation.HandleCallback(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer);
  2259. var
  2260. i, argidx: SizeInt;
  2261. args: TValueArray;
  2262. res: TValue;
  2263. begin
  2264. Assert(fArgLen = Length(aArgs), 'Length of arguments does not match');
  2265. SetLength(args, fArgLen);
  2266. argidx := 0;
  2267. i := 0;
  2268. while i < Length(fArgs) do begin
  2269. if pfArray in fArgs[i].ParamFlags then begin
  2270. Inc(i);
  2271. Assert((i < Length(fArgs)) and (pfHigh in fArgs[i].ParamFlags), 'Expected high parameter after open array parameter');
  2272. TValue.MakeOpenArray(aArgs[i - 1], SizeInt(aArgs[i]), fArgs[i].ParamType, args[argidx]);
  2273. end else if not (pfHidden in fArgs[i].ParamFlags) or (pfSelf in fArgs[i].ParamFlags) then begin
  2274. if Assigned(fArgs[i].ParamType) then
  2275. TValue.Make(aArgs[i], fArgs[i].ParamType, args[argidx])
  2276. else
  2277. TValue.Make(@aArgs[i], TypeInfo(Pointer), args[argidx]);
  2278. end;
  2279. Inc(i);
  2280. Inc(argidx);
  2281. end;
  2282. if Assigned(fCallbackMethod) then
  2283. fCallbackMethod(aContext, args, res)
  2284. else
  2285. fCallbackProc(aContext, args, res);
  2286. { copy back var/out parameters }
  2287. for i := 0 to High(fRefArgs) do begin
  2288. args[fRefArgs[i]].ExtractRawData(aArgs[fRefArgs[i]]);
  2289. end;
  2290. if Assigned(fResult) then
  2291. res.ExtractRawData(aResult);
  2292. end;
  2293. constructor TMethodImplementation.Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackMethod);
  2294. begin
  2295. fCC := aCC;
  2296. fArgs := aArgs;
  2297. fResult := aResult;
  2298. fFlags := aFlags;
  2299. fCallbackMethod := aCallback;
  2300. InitArgs;
  2301. fLowLevelCallback := CreateCallbackMethod(@HandleCallback, fCC, aArgs, aResult, aFlags, aUserData);
  2302. if not Assigned(fLowLevelCallback) then
  2303. raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
  2304. end;
  2305. constructor TMethodImplementation.Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackProc);
  2306. begin
  2307. fCC := aCC;
  2308. fArgs := aArgs;
  2309. fResult := aResult;
  2310. fFlags := aFlags;
  2311. fCallbackProc := aCallback;
  2312. InitArgs;
  2313. fLowLevelCallback := CreateCallbackMethod(@HandleCallback, fCC, aArgs, aResult, aFlags, aUserData);
  2314. if not Assigned(fLowLevelCallback) then
  2315. raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
  2316. end;
  2317. constructor TMethodImplementation.Create;
  2318. begin
  2319. raise EInvalidOpException.Create(SErrMethodImplCreateNoArg);
  2320. end;
  2321. destructor TMethodImplementation.Destroy;
  2322. begin
  2323. fLowLevelCallback.Free;
  2324. inherited Destroy;
  2325. end;
  2326. { TRttiMethod }
  2327. function TRttiMethod.GetHasExtendedInfo: Boolean;
  2328. begin
  2329. Result := False;
  2330. end;
  2331. function TRttiMethod.GetParameters: specialize TArray<TRttiParameter>;
  2332. begin
  2333. Result := GetParameters(False);
  2334. end;
  2335. function TRttiMethod.ToString: String;
  2336. var
  2337. ret: TRttiType;
  2338. n: String;
  2339. params: specialize TArray<TRttiParameter>;
  2340. i: LongInt;
  2341. begin
  2342. if FString = '' then begin
  2343. n := Name;
  2344. if n = '' then
  2345. n := '<unknown>';
  2346. if not HasExtendedInfo then begin
  2347. FString := 'method ' + n;
  2348. end else begin
  2349. ret := ReturnType;
  2350. if IsClassMethod then
  2351. FString := 'class ';
  2352. if IsConstructor then
  2353. FString := FString + 'constructor'
  2354. else if IsDestructor then
  2355. FString := FString + 'destructor'
  2356. else if Assigned(ret) then
  2357. FString := FString + 'function'
  2358. else
  2359. FString := FString + 'procedure';
  2360. FString := FString + ' ' + n;
  2361. params := GetParameters;
  2362. if Length(params) > 0 then begin
  2363. FString := FString + '(';
  2364. for i := 0 to High(params) do begin
  2365. if i > 0 then
  2366. FString := FString + '; ';
  2367. FString := FString + params[i].ToString;
  2368. end;
  2369. FString := FString + ')';
  2370. end;
  2371. if Assigned(ret) then
  2372. FString := FString + ': ' + ret.Name;
  2373. if IsStatic then
  2374. FString := FString + '; static';
  2375. end;
  2376. end;
  2377. Result := FString;
  2378. end;
  2379. function TRttiMethod.Invoke(aInstance: TObject; const aArgs: array of TValue): TValue;
  2380. var
  2381. instance: TValue;
  2382. begin
  2383. TValue.Make(@aInstance, TypeInfo(TObject), instance);
  2384. Result := Invoke(instance, aArgs);
  2385. end;
  2386. function TRttiMethod.Invoke(aInstance: TClass; const aArgs: array of TValue): TValue;
  2387. var
  2388. instance: TValue;
  2389. begin
  2390. TValue.Make(@aInstance, TypeInfo(TClass), instance);
  2391. Result := Invoke(instance, aArgs);
  2392. end;
  2393. function TRttiMethod.Invoke(aInstance: TValue; const aArgs: array of TValue): TValue;
  2394. var
  2395. addr: CodePointer;
  2396. vmt: PCodePointer;
  2397. begin
  2398. if not HasExtendedInfo then
  2399. raise EInvocationError.Create(SErrInvokeInsufficientRtti);
  2400. if IsStatic and not aInstance.IsEmpty then
  2401. raise EInvocationError.CreateFmt(SErrInvokeStaticNoSelf, [Name]);
  2402. if not IsStatic and aInstance.IsEmpty then
  2403. raise EInvocationError.CreateFmt(SErrInvokeNotStaticNeedsSelf, [Name]);
  2404. if not IsStatic and IsClassMethod and not aInstance.IsClass then
  2405. raise EInvocationError.CreateFmt(SErrInvokeClassMethodClassSelf, [Name]);
  2406. addr := Nil;
  2407. if IsStatic then
  2408. addr := CodeAddress
  2409. else begin
  2410. vmt := Nil;
  2411. if aInstance.Kind in [tkInterface, tkInterfaceRaw] then
  2412. vmt := PCodePointer(PPPointer(aInstance.GetReferenceToRawData)^^);
  2413. { ToDo }
  2414. if Assigned(vmt) then
  2415. addr := vmt[VirtualIndex];
  2416. end;
  2417. Result := Rtti.Invoke(Name, addr, CallingConvention, IsStatic, aInstance, aArgs, GetParameters(True), ReturnType);
  2418. end;
  2419. { TRttiInvokableType }
  2420. function TRttiInvokableType.GetParameters: specialize TArray<TRttiParameter>;
  2421. begin
  2422. Result := GetParameters(False);
  2423. end;
  2424. function TRttiInvokableType.CreateImplementation(aCallback: TCallbackMethod): TMethodImplementation;
  2425. var
  2426. params: specialize TArray<TRttiParameter>;
  2427. args: specialize TArray<TFunctionCallParameterInfo>;
  2428. res: PTypeInfo;
  2429. restype: TRttiType;
  2430. resinparam: Boolean;
  2431. i: SizeInt;
  2432. begin
  2433. if not Assigned(aCallback) then
  2434. raise EArgumentNilException.Create(SErrMethodImplNoCallback);
  2435. resinparam := False;
  2436. params := GetParameters(True);
  2437. SetLength(args, Length(params));
  2438. for i := 0 to High(params) do begin
  2439. if Assigned(params[i].ParamType) then
  2440. args[i].ParamType := params[i].ParamType.FTypeInfo
  2441. else
  2442. args[i].ParamType := Nil;
  2443. args[i].ParamFlags := params[i].Flags;
  2444. args[i].ParaLocs := Nil;
  2445. if pfResult in params[i].Flags then
  2446. resinparam := True;
  2447. end;
  2448. restype := GetReturnType;
  2449. if Assigned(restype) and not resinparam then
  2450. res := restype.FTypeInfo
  2451. else
  2452. res := Nil;
  2453. Result := TMethodImplementation.Create(GetCallingConvention, args, res, GetFlags, Self, TMethodImplementationCallbackMethod(aCallback));
  2454. end;
  2455. function TRttiInvokableType.CreateImplementation(aCallback: TCallbackProc): TMethodImplementation;
  2456. var
  2457. params: specialize TArray<TRttiParameter>;
  2458. args: specialize TArray<TFunctionCallParameterInfo>;
  2459. res: PTypeInfo;
  2460. restype: TRttiType;
  2461. resinparam: Boolean;
  2462. i: SizeInt;
  2463. begin
  2464. if not Assigned(aCallback) then
  2465. raise EArgumentNilException.Create(SErrMethodImplNoCallback);
  2466. resinparam := False;
  2467. params := GetParameters(True);
  2468. SetLength(args, Length(params));
  2469. for i := 0 to High(params) do begin
  2470. if Assigned(params[i].ParamType) then
  2471. args[i].ParamType := params[i].ParamType.FTypeInfo
  2472. else
  2473. args[i].ParamType := Nil;
  2474. args[i].ParamFlags := params[i].Flags;
  2475. args[i].ParaLocs := Nil;
  2476. if pfResult in params[i].Flags then
  2477. resinparam := True;
  2478. end;
  2479. restype := GetReturnType;
  2480. if Assigned(restype) and not resinparam then
  2481. res := restype.FTypeInfo
  2482. else
  2483. res := Nil;
  2484. Result := TMethodImplementation.Create(GetCallingConvention, args, res, GetFlags, Self, TMethodImplementationCallbackProc(aCallback));
  2485. end;
  2486. { TRttiMethodType }
  2487. function TRttiMethodType.GetParameters(aWithHidden: Boolean): specialize TArray<TRttiParameter>;
  2488. type
  2489. TParamInfo = record
  2490. Handle: Pointer;
  2491. Flags: TParamFlags;
  2492. Name: String;
  2493. end;
  2494. PParamFlags = ^TParamFlags;
  2495. PCallConv = ^TCallConv;
  2496. PPPTypeInfo = ^PPTypeInfo;
  2497. var
  2498. infos: array of TParamInfo;
  2499. total, visible, i: SizeInt;
  2500. ptr: PByte;
  2501. paramtypes: PPPTypeInfo;
  2502. paramtype: PTypeInfo;
  2503. context: TRttiContext;
  2504. obj: TRttiObject;
  2505. begin
  2506. if aWithHidden and (Length(FParamsAll) > 0) then
  2507. Exit(FParamsAll);
  2508. if not aWithHidden and (Length(FParams) > 0) then
  2509. Exit(FParams);
  2510. ptr := @FTypeData^.ParamList[0];
  2511. visible := 0;
  2512. total := 0;
  2513. if FTypeData^.ParamCount > 0 then begin
  2514. SetLength(infos, FTypeData^.ParamCount);
  2515. while total < FTypeData^.ParamCount do begin
  2516. infos[total].Handle := ptr;
  2517. infos[total].Flags := PParamFlags(ptr)^;
  2518. Inc(ptr, SizeOf(TParamFlags));
  2519. { handle name }
  2520. infos[total].Name := PShortString(ptr)^;
  2521. Inc(ptr, ptr^ + SizeOf(Byte));
  2522. { skip type name }
  2523. Inc(ptr, ptr^ + SizeOf(Byte));
  2524. { align? }
  2525. if not (pfHidden in infos[total].Flags) then
  2526. Inc(visible);
  2527. Inc(total);
  2528. end;
  2529. end;
  2530. if FTypeData^.MethodKind in [mkFunction, mkClassFunction] then begin
  2531. { skip return type name }
  2532. ptr := AlignTypeData(PByte(ptr) + ptr^ + SizeOf(Byte));
  2533. { handle return type }
  2534. FReturnType := GRttiPool.GetType(PPPTypeInfo(ptr)^^);
  2535. Inc(ptr, SizeOf(PPTypeInfo));
  2536. end;
  2537. { handle calling convention }
  2538. FCallConv := PCallConv(ptr)^;
  2539. Inc(ptr, SizeOf(TCallConv));
  2540. SetLength(FParamsAll, FTypeData^.ParamCount);
  2541. SetLength(FParams, visible);
  2542. if FTypeData^.ParamCount > 0 then begin
  2543. context := TRttiContext.Create;
  2544. try
  2545. paramtypes := PPPTypeInfo(ptr);
  2546. visible := 0;
  2547. for i := 0 to FTypeData^.ParamCount - 1 do begin
  2548. obj := context.GetByHandle(infos[i].Handle);
  2549. if Assigned(obj) then
  2550. FParamsAll[i] := obj as TRttiMethodTypeParameter
  2551. else begin
  2552. if Assigned(paramtypes[i]) then
  2553. paramtype := paramtypes[i]^
  2554. else
  2555. paramtype := Nil;
  2556. FParamsAll[i] := TRttiMethodTypeParameter.Create(infos[i].Handle, infos[i].Name, infos[i].Flags, paramtype);
  2557. context.AddObject(FParamsAll[i]);
  2558. end;
  2559. if not (pfHidden in infos[i].Flags) then begin
  2560. FParams[visible] := FParamsAll[i];
  2561. Inc(visible);
  2562. end;
  2563. end;
  2564. finally
  2565. context.Free;
  2566. end;
  2567. end;
  2568. if aWithHidden then
  2569. Result := FParamsAll
  2570. else
  2571. Result := FParams;
  2572. end;
  2573. function TRttiMethodType.GetCallingConvention: TCallConv;
  2574. begin
  2575. { the calling convention is located after the parameters, so get the parameters
  2576. which will also initialize the calling convention }
  2577. GetParameters(True);
  2578. Result := FCallConv;
  2579. end;
  2580. function TRttiMethodType.GetReturnType: TRttiType;
  2581. begin
  2582. if FTypeData^.MethodKind in [mkFunction, mkClassFunction] then begin
  2583. { the return type is located after the parameters, so get the parameters
  2584. which will also initialize the return type }
  2585. GetParameters(True);
  2586. Result := FReturnType;
  2587. end else
  2588. Result := Nil;
  2589. end;
  2590. function TRttiMethodType.GetFlags: TFunctionCallFlags;
  2591. begin
  2592. Result := [];
  2593. end;
  2594. function TRttiMethodType.Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue;
  2595. var
  2596. method: PMethod;
  2597. inst: TValue;
  2598. begin
  2599. if aCallable.Kind <> tkMethod then
  2600. raise EInvocationError.CreateFmt(SErrInvokeCallableNotMethod, [Name]);
  2601. method := PMethod(aCallable.GetReferenceToRawData);
  2602. { by using a pointer we can also use this for non-class instance methods }
  2603. TValue.Make(@method^.Data, PTypeInfo(TypeInfo(Pointer)), inst);
  2604. Result := Rtti.Invoke(Name, method^.Code, CallingConvention, False, inst, aArgs, GetParameters(True), ReturnType);
  2605. end;
  2606. { TRttiProcedureType }
  2607. function TRttiProcedureType.GetParameters(aWithHidden: Boolean): specialize TArray<TRttiParameter>;
  2608. var
  2609. visible, i: SizeInt;
  2610. param: PProcedureParam;
  2611. obj: TRttiObject;
  2612. context: TRttiContext;
  2613. begin
  2614. if aWithHidden and (Length(FParamsAll) > 0) then
  2615. Exit(FParamsAll);
  2616. if not aWithHidden and (Length(FParams) > 0) then
  2617. Exit(FParams);
  2618. if FTypeData^.ProcSig.ParamCount = 0 then
  2619. Exit(Nil);
  2620. SetLength(FParamsAll, FTypeData^.ProcSig.ParamCount);
  2621. SetLength(FParams, FTypeData^.ProcSig.ParamCount);
  2622. context := TRttiContext.Create;
  2623. try
  2624. param := AlignTypeData(PProcedureParam(@FTypeData^.ProcSig.ParamCount + SizeOf(FTypeData^.ProcSig.ParamCount)));
  2625. visible := 0;
  2626. for i := 0 to FTypeData^.ProcSig.ParamCount - 1 do begin
  2627. obj := context.GetByHandle(param);
  2628. if Assigned(obj) then
  2629. FParamsAll[i] := obj as TRttiMethodTypeParameter
  2630. else begin
  2631. FParamsAll[i] := TRttiMethodTypeParameter.Create(param, param^.Name, param^.ParamFlags, param^.ParamType);
  2632. context.AddObject(FParamsAll[i]);
  2633. end;
  2634. if not (pfHidden in param^.ParamFlags) then begin
  2635. FParams[visible] := FParamsAll[i];
  2636. Inc(visible);
  2637. end;
  2638. param := PProcedureParam(AlignTypeData(PByte(@param^.Name) + Length(param^.Name) + SizeOf(param^.Name[0])));
  2639. end;
  2640. SetLength(FParams, visible);
  2641. finally
  2642. context.Free;
  2643. end;
  2644. if aWithHidden then
  2645. Result := FParamsAll
  2646. else
  2647. Result := FParams;
  2648. end;
  2649. function TRttiProcedureType.GetCallingConvention: TCallConv;
  2650. begin
  2651. Result := FTypeData^.ProcSig.CC;
  2652. end;
  2653. function TRttiProcedureType.GetReturnType: TRttiType;
  2654. var
  2655. context: TRttiContext;
  2656. begin
  2657. if not Assigned(FTypeData^.ProcSig.ResultTypeRef) then
  2658. Exit(Nil);
  2659. context := TRttiContext.Create;
  2660. try
  2661. Result := context.GetType(FTypeData^.ProcSig.ResultTypeRef^);
  2662. finally
  2663. context.Free;
  2664. end;
  2665. end;
  2666. function TRttiProcedureType.GetFlags: TFunctionCallFlags;
  2667. begin
  2668. Result := [fcfStatic];
  2669. end;
  2670. function TRttiProcedureType.Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue;
  2671. begin
  2672. if aCallable.Kind <> tkProcVar then
  2673. raise EInvocationError.CreateFmt(SErrInvokeCallableNotProc, [Name]);
  2674. Result := Rtti.Invoke(Name, PCodePointer(aCallable.GetReferenceToRawData)^, CallingConvention, True, TValue.Empty, aArgs, GetParameters(True), ReturnType);
  2675. end;
  2676. { TRttiStringType }
  2677. function TRttiStringType.GetStringKind: TRttiStringKind;
  2678. begin
  2679. case TypeKind of
  2680. tkSString : result := skShortString;
  2681. tkLString : result := skAnsiString;
  2682. tkAString : result := skAnsiString;
  2683. tkUString : result := skUnicodeString;
  2684. tkWString : result := skWideString;
  2685. end;
  2686. end;
  2687. { TRttiInterfaceType }
  2688. function TRttiInterfaceType.IntfMethodCount: Word;
  2689. var
  2690. parent: TRttiInterfaceType;
  2691. table: PIntfMethodTable;
  2692. begin
  2693. parent := GetIntfBaseType;
  2694. if Assigned(parent) then
  2695. Result := parent.IntfMethodCount
  2696. else
  2697. Result := 0;
  2698. table := MethodTable;
  2699. if Assigned(table) then
  2700. Inc(Result, table^.Count);
  2701. end;
  2702. function TRttiInterfaceType.GetBaseType: TRttiType;
  2703. begin
  2704. Result := GetIntfBaseType;
  2705. end;
  2706. function TRttiInterfaceType.GetGUIDStr: String;
  2707. begin
  2708. Result := GUIDToString(GUID);
  2709. end;
  2710. function TRttiInterfaceType.GetDeclaredMethods: specialize TArray<TRttiMethod>;
  2711. var
  2712. methtable: PIntfMethodTable;
  2713. count, index: Word;
  2714. method: PIntfMethodEntry;
  2715. context: TRttiContext;
  2716. obj: TRttiObject;
  2717. parent: TRttiInterfaceType;
  2718. parentmethodcount: Word;
  2719. begin
  2720. if Assigned(fDeclaredMethods) then
  2721. Exit(fDeclaredMethods);
  2722. methtable := MethodTable;
  2723. if not Assigned(methtable) then
  2724. Exit(Nil);
  2725. if (methtable^.Count = 0) or (methtable^.RTTICount = $ffff) then
  2726. Exit(Nil);
  2727. parent := GetIntfBaseType;
  2728. if Assigned(parent) then
  2729. parentmethodcount := parent.IntfMethodCount
  2730. else
  2731. parentmethodcount := 0;
  2732. SetLength(fDeclaredMethods, methtable^.Count);
  2733. context := TRttiContext.Create;
  2734. try
  2735. method := methtable^.Method[0];
  2736. count := methtable^.Count;
  2737. while count > 0 do begin
  2738. index := methtable^.Count - count;
  2739. obj := context.GetByHandle(method);
  2740. if Assigned(obj) then
  2741. fDeclaredMethods[index] := obj as TRttiMethod
  2742. else begin
  2743. fDeclaredMethods[index] := TRttiIntfMethod.Create(Self, method, parentmethodcount + index);
  2744. context.AddObject(fDeclaredMethods[index]);
  2745. end;
  2746. method := method^.Next;
  2747. Dec(count);
  2748. end;
  2749. finally
  2750. context.Free;
  2751. end;
  2752. Result := fDeclaredMethods;
  2753. end;
  2754. { TRttiInstanceType }
  2755. function TRttiInstanceType.GetMetaClassType: TClass;
  2756. begin
  2757. result := FTypeData^.ClassType;
  2758. end;
  2759. function TRttiInstanceType.GetDeclaringUnitName: string;
  2760. begin
  2761. result := FTypeData^.UnitName;
  2762. end;
  2763. function TRttiInstanceType.GetBaseType: TRttiType;
  2764. var
  2765. AContext: TRttiContext;
  2766. begin
  2767. AContext := TRttiContext.Create;
  2768. try
  2769. result := AContext.GetType(FTypeData^.ParentInfo);
  2770. finally
  2771. AContext.Free;
  2772. end;
  2773. end;
  2774. function TRttiInstanceType.GetIsInstance: boolean;
  2775. begin
  2776. Result:=True;
  2777. end;
  2778. function TRttiInstanceType.GetTypeSize: integer;
  2779. begin
  2780. Result:=sizeof(TObject);
  2781. end;
  2782. function TRttiInstanceType.GetProperties: specialize TArray<TRttiProperty>;
  2783. var
  2784. TypeInfo: PTypeInfo;
  2785. TypeRttiType: TRttiType;
  2786. TD: PTypeData;
  2787. PPD: PPropData;
  2788. TP: PPropInfo;
  2789. Count: longint;
  2790. obj: TRttiObject;
  2791. begin
  2792. if not FPropertiesResolved then
  2793. begin
  2794. TypeInfo := FTypeInfo;
  2795. // Get the total properties count
  2796. SetLength(FProperties,FTypeData^.PropCount);
  2797. TypeRttiType:= self;
  2798. repeat
  2799. TD:=GetTypeData(TypeInfo);
  2800. // published properties count for this object
  2801. // skip the attribute-info if available
  2802. PPD := PClassData(TD)^.PropertyTable;
  2803. Count:=PPD^.PropCount;
  2804. // Now point TP to first propinfo record.
  2805. TP:=PPropInfo(@PPD^.PropList);
  2806. While Count>0 do
  2807. begin
  2808. // Don't overwrite properties with the same name
  2809. if FProperties[TP^.NameIndex]=nil then begin
  2810. obj := GRttiPool.GetByHandle(TP);
  2811. if Assigned(obj) then
  2812. FProperties[TP^.NameIndex] := obj as TRttiProperty
  2813. else begin
  2814. FProperties[TP^.NameIndex] := TRttiProperty.Create(TypeRttiType, TP);
  2815. GRttiPool.AddObject(FProperties[TP^.NameIndex]);
  2816. end;
  2817. end;
  2818. // Point to TP next propinfo record.
  2819. // Located at Name[Length(Name)+1] !
  2820. TP:=TP^.Next;
  2821. Dec(Count);
  2822. end;
  2823. TypeInfo:=TD^.Parentinfo;
  2824. TypeRttiType:= GRttiPool.GetType(TypeInfo);
  2825. until TypeInfo=nil;
  2826. end;
  2827. result := FProperties;
  2828. end;
  2829. { TRttiMember }
  2830. function TRttiMember.GetVisibility: TMemberVisibility;
  2831. begin
  2832. result := mvPublished;
  2833. end;
  2834. constructor TRttiMember.Create(AParent: TRttiType);
  2835. begin
  2836. inherited Create();
  2837. FParent := AParent;
  2838. end;
  2839. { TRttiProperty }
  2840. function TRttiProperty.GetPropertyType: TRttiType;
  2841. begin
  2842. result := GRttiPool.GetType(FPropInfo^.PropType);
  2843. end;
  2844. function TRttiProperty.GetIsReadable: boolean;
  2845. begin
  2846. result := assigned(FPropInfo^.GetProc);
  2847. end;
  2848. function TRttiProperty.GetIsWritable: boolean;
  2849. begin
  2850. result := assigned(FPropInfo^.SetProc);
  2851. end;
  2852. function TRttiProperty.GetVisibility: TMemberVisibility;
  2853. begin
  2854. // At this moment only pulished rtti-property-info is supported by fpc
  2855. result := mvPublished;
  2856. end;
  2857. function TRttiProperty.GetName: string;
  2858. begin
  2859. Result:=FPropInfo^.Name;
  2860. end;
  2861. function TRttiProperty.GetHandle: Pointer;
  2862. begin
  2863. Result := FPropInfo;
  2864. end;
  2865. constructor TRttiProperty.Create(AParent: TRttiType; APropInfo: PPropInfo);
  2866. begin
  2867. inherited Create(AParent);
  2868. FPropInfo := APropInfo;
  2869. end;
  2870. function TRttiProperty.GetValue(Instance: pointer): TValue;
  2871. procedure ValueFromBool(value: Int64);
  2872. var
  2873. b8: Boolean;
  2874. b16: Boolean16;
  2875. b32: Boolean32;
  2876. bb: ByteBool;
  2877. bw: WordBool;
  2878. bl: LongBool;
  2879. td: PTypeData;
  2880. p: Pointer;
  2881. begin
  2882. td := GetTypeData(FPropInfo^.PropType);
  2883. case td^.OrdType of
  2884. otUByte:
  2885. begin
  2886. b8 := Boolean(value);
  2887. p := @b8;
  2888. end;
  2889. otUWord:
  2890. begin
  2891. b16 := Boolean16(value);
  2892. p := @b16;
  2893. end;
  2894. otULong:
  2895. begin
  2896. b32 := Boolean32(value);
  2897. p := @b32;
  2898. end;
  2899. otSByte:
  2900. begin
  2901. bb := ByteBool(value);
  2902. p := @bb;
  2903. end;
  2904. otSWord:
  2905. begin
  2906. bw := WordBool(value);
  2907. p := @bw;
  2908. end;
  2909. otSLong:
  2910. begin
  2911. bl := LongBool(value);
  2912. p := @bl;
  2913. end;
  2914. end;
  2915. TValue.Make(p, FPropInfo^.PropType, result);
  2916. end;
  2917. procedure ValueFromInt(value: Int64);
  2918. var
  2919. i8: UInt8;
  2920. i16: UInt16;
  2921. i32: UInt32;
  2922. td: PTypeData;
  2923. p: Pointer;
  2924. begin
  2925. td := GetTypeData(FPropInfo^.PropType);
  2926. case td^.OrdType of
  2927. otUByte,
  2928. otSByte:
  2929. begin
  2930. i8 := value;
  2931. p := @i8;
  2932. end;
  2933. otUWord,
  2934. otSWord:
  2935. begin
  2936. i16 := value;
  2937. p := @i16;
  2938. end;
  2939. otULong,
  2940. otSLong:
  2941. begin
  2942. i32 := value;
  2943. p := @i32;
  2944. end;
  2945. end;
  2946. TValue.Make(p, FPropInfo^.PropType, result);
  2947. end;
  2948. var
  2949. s: string;
  2950. ss: ShortString;
  2951. i: int64;
  2952. c: Char;
  2953. wc: WideChar;
  2954. begin
  2955. case FPropinfo^.PropType^.Kind of
  2956. tkSString:
  2957. begin
  2958. ss := GetStrProp(TObject(Instance), FPropInfo);
  2959. TValue.Make(@ss, FPropInfo^.PropType, result);
  2960. end;
  2961. tkAString:
  2962. begin
  2963. s := GetStrProp(TObject(Instance), FPropInfo);
  2964. TValue.Make(@s, FPropInfo^.PropType, result);
  2965. end;
  2966. tkBool:
  2967. begin
  2968. i := GetOrdProp(TObject(Instance), FPropInfo);
  2969. ValueFromBool(i);
  2970. end;
  2971. tkInteger:
  2972. begin
  2973. i := GetOrdProp(TObject(Instance), FPropInfo);
  2974. ValueFromInt(i);
  2975. end;
  2976. tkChar:
  2977. begin
  2978. c := AnsiChar(GetOrdProp(TObject(Instance), FPropInfo));
  2979. TValue.Make(@c, FPropInfo^.PropType, result);
  2980. end;
  2981. tkWChar:
  2982. begin
  2983. wc := WideChar(GetOrdProp(TObject(Instance), FPropInfo));
  2984. TValue.Make(@wc, FPropInfo^.PropType, result);
  2985. end;
  2986. tkInt64,
  2987. tkQWord:
  2988. begin
  2989. i := GetOrdProp(TObject(Instance), FPropInfo);
  2990. TValue.Make(@i, FPropInfo^.PropType, result);
  2991. end;
  2992. else
  2993. result := TValue.Empty;
  2994. end
  2995. end;
  2996. procedure TRttiProperty.SetValue(Instance: pointer; const AValue: TValue);
  2997. begin
  2998. case FPropinfo^.PropType^.Kind of
  2999. tkSString,
  3000. tkAString:
  3001. SetStrProp(TObject(Instance), FPropInfo, AValue.AsString);
  3002. tkInteger,
  3003. tkInt64,
  3004. tkQWord,
  3005. tkChar,
  3006. tkBool,
  3007. tkWChar:
  3008. SetOrdProp(TObject(Instance), FPropInfo, AValue.AsOrdinal);
  3009. else
  3010. raise exception.createFmt(SErrUnableToSetValueForType, [PropertyType.Name]);
  3011. end
  3012. end;
  3013. function TRttiType.GetIsInstance: boolean;
  3014. begin
  3015. result := false;
  3016. end;
  3017. function TRttiType.GetIsManaged: boolean;
  3018. begin
  3019. result := Rtti.IsManaged(FTypeInfo);
  3020. end;
  3021. function TRttiType.GetIsOrdinal: boolean;
  3022. begin
  3023. result := false;
  3024. end;
  3025. function TRttiType.GetIsRecord: boolean;
  3026. begin
  3027. result := false;
  3028. end;
  3029. function TRttiType.GetIsSet: boolean;
  3030. begin
  3031. result := false;
  3032. end;
  3033. function TRttiType.GetAsInstance: TRttiInstanceType;
  3034. begin
  3035. // This is a ridicoulous design, but Delphi-compatible...
  3036. result := TRttiInstanceType(self);
  3037. end;
  3038. function TRttiType.GetBaseType: TRttiType;
  3039. begin
  3040. result := nil;
  3041. end;
  3042. function TRttiType.GetTypeKind: TTypeKind;
  3043. begin
  3044. result := FTypeInfo^.Kind;
  3045. end;
  3046. function TRttiType.GetTypeSize: integer;
  3047. begin
  3048. result := -1;
  3049. end;
  3050. function TRttiType.GetName: string;
  3051. begin
  3052. Result:=FTypeInfo^.Name;
  3053. end;
  3054. function TRttiType.GetHandle: Pointer;
  3055. begin
  3056. Result := FTypeInfo;
  3057. end;
  3058. constructor TRttiType.Create(ATypeInfo: PTypeInfo);
  3059. begin
  3060. inherited Create();
  3061. FTypeInfo:=ATypeInfo;
  3062. if assigned(FTypeInfo) then
  3063. FTypeData:=GetTypeData(ATypeInfo);
  3064. end;
  3065. function TRttiType.GetProperties: specialize TArray<TRttiProperty>;
  3066. begin
  3067. Result := Nil;
  3068. end;
  3069. function TRttiType.GetProperty(const AName: string): TRttiProperty;
  3070. var
  3071. FPropList: specialize TArray<TRttiProperty>;
  3072. i: Integer;
  3073. begin
  3074. result := nil;
  3075. FPropList := GetProperties;
  3076. for i := 0 to length(FPropList)-1 do
  3077. if sametext(FPropList[i].Name,AName) then
  3078. begin
  3079. result := FPropList[i];
  3080. break;
  3081. end;
  3082. end;
  3083. function TRttiType.GetMethods: specialize TArray<TRttiMethod>;
  3084. var
  3085. parentmethods, selfmethods: specialize TArray<TRttiMethod>;
  3086. parent: TRttiType;
  3087. begin
  3088. if Assigned(fMethods) then
  3089. Exit(fMethods);
  3090. selfmethods := GetDeclaredMethods;
  3091. parent := GetBaseType;
  3092. if Assigned(parent) then begin
  3093. parentmethods := parent.GetMethods;
  3094. end;
  3095. fMethods := Concat(parentmethods, selfmethods);
  3096. Result := fMethods;
  3097. end;
  3098. function TRttiType.GetMethod(const aName: String): TRttiMethod;
  3099. var
  3100. methods: specialize TArray<TRttiMethod>;
  3101. method: TRttiMethod;
  3102. begin
  3103. methods := GetMethods;
  3104. for method in methods do
  3105. if SameText(method.Name, AName) then
  3106. Exit(method);
  3107. Result := Nil;
  3108. end;
  3109. function TRttiType.GetDeclaredMethods: specialize TArray<TRttiMethod>;
  3110. begin
  3111. Result := Nil;
  3112. end;
  3113. { TRttiNamedObject }
  3114. function TRttiNamedObject.GetName: string;
  3115. begin
  3116. result := '';
  3117. end;
  3118. { TRttiContext }
  3119. class function TRttiContext.Create: TRttiContext;
  3120. begin
  3121. result.FContextToken := nil;
  3122. end;
  3123. procedure TRttiContext.Free;
  3124. begin
  3125. FContextToken := nil;
  3126. end;
  3127. function TRttiContext.GetByHandle(AHandle: Pointer): TRttiObject;
  3128. begin
  3129. if not Assigned(FContextToken) then
  3130. FContextToken := TPoolToken.Create;
  3131. Result := (FContextToken as IPooltoken).RttiPool.GetByHandle(AHandle);
  3132. end;
  3133. procedure TRttiContext.AddObject(AObject: TRttiObject);
  3134. begin
  3135. if not Assigned(FContextToken) then
  3136. FContextToken := TPoolToken.Create;
  3137. (FContextToken as IPooltoken).RttiPool.AddObject(AObject);
  3138. end;
  3139. function TRttiContext.GetType(ATypeInfo: PTypeInfo): TRttiType;
  3140. begin
  3141. if not assigned(FContextToken) then
  3142. FContextToken := TPoolToken.Create;
  3143. result := (FContextToken as IPooltoken).RttiPool.GetType(ATypeInfo);
  3144. end;
  3145. function TRttiContext.GetType(AClass: TClass): TRttiType;
  3146. begin
  3147. if assigned(AClass) then
  3148. result := GetType(PTypeInfo(AClass.ClassInfo))
  3149. else
  3150. result := nil;
  3151. end;
  3152. {function TRttiContext.GetTypes: specialize TArray<TRttiType>;
  3153. begin
  3154. if not assigned(FContextToken) then
  3155. FContextToken := TPoolToken.Create;
  3156. result := (FContextToken as IPooltoken).RttiPool.GetTypes;
  3157. end;}
  3158. {$ifndef InLazIDE}
  3159. {$if defined(CPUI386) or (defined(CPUX86_64) and defined(WIN64))}
  3160. {$I invoke.inc}
  3161. {$endif}
  3162. {$endif}
  3163. initialization
  3164. PoolRefCount := 0;
  3165. InitDefaultFunctionCallManager;
  3166. {$ifdef SYSTEM_HAS_INVOKE}
  3167. InitSystemFunctionCallManager;
  3168. {$endif}
  3169. end.