rtti.pp 109 KB

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