rtti.pp 106 KB

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