2
0

rtti.pp 142 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980
  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. {$IFNDEF FPC_DOTTEDUNITS}
  13. unit Rtti;
  14. {$ENDIF}
  15. {$mode objfpc}{$H+}
  16. {$modeswitch advancedrecords}
  17. {$goto on}
  18. {$Assertions on}
  19. { Note: since the Lazarus IDE is not yet capable of correctly handling generic
  20. functions it is best to define a InLazIDE define inside the IDE that disables
  21. the generic code for CodeTools. To do this do this:
  22. - go to Tools -> Codetools Defines Editor
  23. - go to Edit -> Insert Node Below -> Define Recurse
  24. - enter the following values:
  25. Name: InLazIDE
  26. Description: Define InLazIDE everywhere
  27. Variable: InLazIDE
  28. Value from text: 1
  29. }
  30. {$ifdef InLazIDE}
  31. {$define NoGenericMethods}
  32. {$endif}
  33. interface
  34. {$IFDEF FPC_DOTTEDUNITS}
  35. uses
  36. System.Classes,
  37. System.SysUtils,
  38. System.TypInfo;
  39. {$ELSE FPC_DOTTEDUNITS}
  40. uses
  41. Classes,
  42. SysUtils,
  43. typinfo;
  44. {$ENDIF FPC_DOTTEDUNITS}
  45. type
  46. TRttiObject = class;
  47. TRttiType = class;
  48. TRttiMethod = class;
  49. TRttiProperty = class;
  50. TRttiInstanceType = class;
  51. TCustomAttributeClass = class of TCustomAttribute;
  52. TRttiClass = class of TRttiObject;
  53. TCustomAttributeArray = specialize TArray<TCustomAttribute>;
  54. TFunctionCallCallback = class
  55. protected
  56. function GetCodeAddress: CodePointer; virtual; abstract;
  57. public
  58. property CodeAddress: CodePointer read GetCodeAddress;
  59. end;
  60. TFunctionCallFlag = (
  61. fcfStatic
  62. );
  63. TFunctionCallFlags = set of TFunctionCallFlag;
  64. TFunctionCallParameterInfo = record
  65. ParamType: PTypeInfo;
  66. ParamFlags: TParamFlags;
  67. ParaLocs: PParameterLocations;
  68. end;
  69. IValueData = interface
  70. ['{1338B2F3-2C21-4798-A641-CA2BC5BF2396}']
  71. procedure ExtractRawData(ABuffer: pointer);
  72. procedure ExtractRawDataNoCopy(ABuffer: pointer);
  73. function GetDataSize: SizeInt;
  74. function GetReferenceToRawData: pointer;
  75. end;
  76. TValueData = record
  77. FTypeInfo: PTypeInfo;
  78. FValueData: IValueData;
  79. case integer of
  80. 0: (FAsUByte: Byte);
  81. 1: (FAsUWord: Word);
  82. 2: (FAsULong: LongWord);
  83. 3: (FAsObject: Pointer);
  84. 4: (FAsClass: TClass);
  85. 5: (FAsSByte: Shortint);
  86. 6: (FAsSWord: Smallint);
  87. 7: (FAsSLong: LongInt);
  88. 8: (FAsSingle: Single);
  89. 9: (FAsDouble: Double);
  90. 10: (FAsExtended: Extended);
  91. 11: (FAsComp: Comp);
  92. 12: (FAsCurr: Currency);
  93. 13: (FAsUInt64: QWord);
  94. 14: (FAsSInt64: Int64);
  95. 15: (FAsMethod: TMethod);
  96. 16: (FAsPointer: Pointer);
  97. { FPC addition for open arrays }
  98. 17: (FArrLength: SizeInt; FElSize: SizeInt);
  99. end;
  100. { TValue }
  101. TValue = record
  102. private
  103. FData: TValueData;
  104. function GetDataSize: SizeInt;
  105. function GetTypeDataProp: PTypeData; inline;
  106. function GetTypeInfo: PTypeInfo; inline;
  107. function GetTypeKind: TTypeKind; inline;
  108. function GetIsEmpty: boolean; inline;
  109. procedure Init; inline;
  110. public
  111. class function Empty: TValue; static;
  112. class procedure Make(ABuffer: pointer; ATypeInfo: PTypeInfo; out result: TValue); static;
  113. class procedure Make(AValue: NativeInt; ATypeInfo: PTypeInfo; out Result: TValue); static; inline;
  114. { Note: a TValue based on an open array is only valid until the routine having the open array parameter is left! }
  115. class procedure MakeOpenArray(AArray: Pointer; ALength: SizeInt; ATypeInfo: PTypeInfo; out Result: TValue); static;
  116. {$ifndef NoGenericMethods}
  117. generic class procedure Make<T>(const AValue: T; out Result: TValue); static; inline;
  118. generic class function From<T>(constref aValue: T): TValue; static; inline;
  119. { Note: a TValue based on an open array is only valid until the routine having the open array parameter is left! }
  120. generic class function FromOpenArray<T>(constref aValue: array of T): TValue; static; inline;
  121. {$endif}
  122. class function FromOrdinal(aTypeInfo: PTypeInfo; aValue: Int64): TValue; static; {inline;}
  123. class function FromArray(aArrayTypeInfo: PTypeInfo; const aValues: array of TValue): TValue; static;
  124. class function FromVarRec(const aValue: TVarRec): TValue; static;
  125. class function FromVariant(const aValue : Variant) : TValue; static;
  126. function IsArray: boolean; inline;
  127. function IsOpenArray: Boolean; inline;
  128. function AsString: string; inline;
  129. function AsUnicodeString: UnicodeString;
  130. function AsAnsiString: AnsiString;
  131. function AsExtended: Extended;
  132. function IsClass: boolean; inline;
  133. function AsClass: TClass;
  134. function IsObject: boolean; inline;
  135. function AsObject: TObject;
  136. function IsOrdinal: boolean; inline;
  137. function AsOrdinal: Int64;
  138. function AsBoolean: boolean;
  139. function AsCurrency: Currency;
  140. function AsSingle : Single;
  141. function AsDateTime : TDateTime;
  142. function AsDouble : Double;
  143. function AsInteger: Integer;
  144. function AsError: HRESULT;
  145. function AsChar: AnsiChar; inline;
  146. function AsAnsiChar: AnsiChar;
  147. function AsWideChar: WideChar;
  148. function AsInt64: Int64;
  149. function AsUInt64: QWord;
  150. function AsInterface: IInterface;
  151. function AsPointer : Pointer;
  152. function AsVariant : Variant;
  153. function ToString: String;
  154. function GetArrayLength: SizeInt;
  155. function GetArrayElement(AIndex: SizeInt): TValue;
  156. procedure SetArrayElement(AIndex: SizeInt; constref AValue: TValue);
  157. function IsType(ATypeInfo: PTypeInfo): boolean; inline;
  158. {$ifndef NoGenericMethods}
  159. generic function IsType<T>: Boolean; inline;
  160. {$endif}
  161. function TryAsOrdinal(out AResult: int64): boolean;
  162. function GetReferenceToRawData: Pointer;
  163. procedure ExtractRawData(ABuffer: Pointer);
  164. procedure ExtractRawDataNoCopy(ABuffer: Pointer);
  165. class operator := (const AValue: ShortString): TValue; inline;
  166. class operator := (const AValue: AnsiString): TValue; inline;
  167. class operator := (const AValue: UnicodeString): TValue; inline;
  168. class operator := (const AValue: WideString): TValue; inline;
  169. class operator := (AValue: LongInt): TValue; inline;
  170. class operator := (AValue: SmallInt): TValue; inline;
  171. class operator := (AValue: ShortInt): TValue; inline;
  172. class operator := (AValue: Byte): TValue; inline;
  173. class operator := (AValue: Word): TValue; inline;
  174. class operator := (AValue: Cardinal): TValue; inline;
  175. class operator := (AValue: Single): TValue; inline;
  176. class operator := (AValue: Double): TValue; inline;
  177. {$ifdef FPC_HAS_TYPE_EXTENDED}
  178. class operator := (AValue: Extended): TValue; inline;
  179. {$endif}
  180. class operator := (AValue: Currency): TValue; inline;
  181. class operator := (AValue: Comp): TValue; inline;
  182. class operator := (AValue: Int64): TValue; inline;
  183. class operator := (AValue: QWord): TValue; inline;
  184. class operator := (AValue: TObject): TValue; inline;
  185. class operator := (AValue: TClass): TValue; inline;
  186. class operator := (AValue: Boolean): TValue; inline;
  187. class operator := (AValue: IUnknown): TValue; inline;
  188. class operator := (AValue: TVarRec): TValue; inline;
  189. property DataSize: SizeInt read GetDataSize;
  190. property Kind: TTypeKind read GetTypeKind;
  191. property TypeData: PTypeData read GetTypeDataProp;
  192. property TypeInfo: PTypeInfo read GetTypeInfo;
  193. property IsEmpty: boolean read GetIsEmpty;
  194. end;
  195. PValue = ^TValue;
  196. TValueArray = specialize TArray<TValue>;
  197. { TRttiContext }
  198. TRttiContext = record
  199. private
  200. FContextToken: IInterface;
  201. function GetByHandle(AHandle: Pointer): TRttiObject;
  202. procedure AddObject(AObject: TRttiObject);
  203. public
  204. class function Create: TRttiContext; static;
  205. procedure Free;
  206. function GetType(ATypeInfo: PTypeInfo): TRttiType;
  207. function GetType(AClass: TClass): TRttiType;
  208. //function GetTypes: specialize TArray<TRttiType>;
  209. end;
  210. { TRttiObject }
  211. TRttiObject = class abstract
  212. protected
  213. function GetHandle: Pointer; virtual; abstract;
  214. public
  215. function HasAttribute(aClass: TCustomAttributeClass): Boolean;
  216. function GetAttribute(aClass: TCustomAttributeClass): TCustomAttribute;
  217. generic function GetAttribute<T>: T;
  218. generic function HasAttribute<T>: Boolean;
  219. function GetAttributes: TCustomAttributeArray; virtual; abstract;
  220. property Handle: Pointer read GetHandle;
  221. end;
  222. { TRttiNamedObject }
  223. TRttiNamedObject = class(TRttiObject)
  224. protected
  225. function GetName: string; virtual;
  226. public
  227. function HasName(const aName: string): Boolean;
  228. property Name: string read GetName;
  229. end;
  230. { TRttiType }
  231. TRttiType = class(TRttiNamedObject)
  232. private
  233. FTypeInfo: PTypeInfo;
  234. FAttributesResolved: boolean;
  235. FAttributes: TCustomAttributeArray;
  236. FMethods: specialize TArray<TRttiMethod>;
  237. function GetAsInstance: TRttiInstanceType;
  238. protected
  239. FTypeData: PTypeData;
  240. function GetName: string; override;
  241. function GetHandle: Pointer; override;
  242. function GetIsInstance: boolean; virtual;
  243. function GetIsManaged: boolean; virtual;
  244. function GetIsOrdinal: boolean; virtual;
  245. function GetIsRecord: boolean; virtual;
  246. function GetIsSet: boolean; virtual;
  247. function GetTypeKind: TTypeKind; virtual;
  248. function GetTypeSize: integer; virtual;
  249. function GetBaseType: TRttiType; virtual;
  250. public
  251. constructor Create(ATypeInfo : PTypeInfo);
  252. destructor Destroy; override;
  253. function GetAttributes: TCustomAttributeArray; override;
  254. function GetProperties: specialize TArray<TRttiProperty>; virtual;
  255. function GetProperty(const AName: string): TRttiProperty; virtual;
  256. function GetMethods: specialize TArray<TRttiMethod>; virtual;
  257. function GetMethod(const aName: String): TRttiMethod; virtual;
  258. function GetDeclaredMethods: specialize TArray<TRttiMethod>; virtual;
  259. property IsInstance: boolean read GetIsInstance;
  260. property isManaged: boolean read GetIsManaged;
  261. property IsOrdinal: boolean read GetIsOrdinal;
  262. property IsRecord: boolean read GetIsRecord;
  263. property IsSet: boolean read GetIsSet;
  264. property BaseType: TRttiType read GetBaseType;
  265. property Handle: PTypeInfo read FTypeInfo;
  266. property AsInstance: TRttiInstanceType read GetAsInstance;
  267. property TypeKind: TTypeKind read GetTypeKind;
  268. property TypeSize: integer read GetTypeSize;
  269. end;
  270. { TRttiFloatType }
  271. TRttiFloatType = class(TRttiType)
  272. private
  273. function GetFloatType: TFloatType; inline;
  274. protected
  275. function GetTypeSize: integer; override;
  276. public
  277. property FloatType: TFloatType read GetFloatType;
  278. end;
  279. TRttiOrdinalType = class(TRttiType)
  280. private
  281. function GetMaxValue: LongInt; inline;
  282. function GetMinValue: LongInt; inline;
  283. function GetOrdType: TOrdType; inline;
  284. protected
  285. function GetTypeSize: Integer; override;
  286. public
  287. property OrdType: TOrdType read GetOrdType;
  288. property MinValue: LongInt read GetMinValue;
  289. property MaxValue: LongInt read GetMaxValue;
  290. end;
  291. TRttiInt64Type = class(TRttiType)
  292. private
  293. function GetMaxValue: Int64; inline;
  294. function GetMinValue: Int64; inline;
  295. function GetUnsigned: Boolean; inline;
  296. protected
  297. function GetTypeSize: integer; override;
  298. public
  299. property MinValue: Int64 read GetMinValue;
  300. property MaxValue: Int64 read GetMaxValue;
  301. property Unsigned: Boolean read GetUnsigned;
  302. end;
  303. TRttiStringKind = (skShortString, skAnsiString, skWideString, skUnicodeString);
  304. { TRttiStringType }
  305. TRttiStringType = class(TRttiType)
  306. private
  307. function GetStringKind: TRttiStringKind;
  308. public
  309. property StringKind: TRttiStringKind read GetStringKind;
  310. end;
  311. TRttiAnsiStringType = class(TRttiStringType)
  312. private
  313. function GetCodePage: Word;
  314. public
  315. property CodePage: Word read GetCodePage;
  316. end;
  317. TRttiPointerType = class(TRttiType)
  318. private
  319. function GetReferredType: TRttiType;
  320. public
  321. property ReferredType: TRttiType read GetReferredType;
  322. end;
  323. TRttiArrayType = class(TRttiType)
  324. private
  325. function GetDimensionCount: SizeUInt; inline;
  326. function GetDimension(aIndex: SizeInt): TRttiType; inline;
  327. function GetElementType: TRttiType; inline;
  328. function GetTotalElementCount: SizeInt; inline;
  329. public
  330. property DimensionCount: SizeUInt read GetDimensionCount;
  331. property Dimensions[Index: SizeInt]: TRttiType read GetDimension;
  332. property ElementType: TRttiType read GetElementType;
  333. property TotalElementCount: SizeInt read GetTotalElementCount;
  334. end;
  335. TRttiDynamicArrayType = class(TRttiType)
  336. private
  337. function GetDeclaringUnitName: String; inline;
  338. function GetElementSize: SizeUInt; inline;
  339. function GetElementType: TRttiType; inline;
  340. function GetOleAutoVarType: TVarType; inline;
  341. public
  342. property DeclaringUnitName: String read GetDeclaringUnitName;
  343. property ElementSize: SizeUInt read GetElementSize;
  344. property ElementType: TRttiType read GetElementType;
  345. property OleAutoVarType: TVarType read GetOleAutoVarType;
  346. end;
  347. { TRttiMember }
  348. TMemberVisibility=(mvPrivate, mvProtected, mvPublic, mvPublished);
  349. TRttiMember = class(TRttiNamedObject)
  350. private
  351. FParent: TRttiType;
  352. protected
  353. function GetVisibility: TMemberVisibility; virtual;
  354. public
  355. constructor Create(AParent: TRttiType);
  356. property Visibility: TMemberVisibility read GetVisibility;
  357. property Parent: TRttiType read FParent;
  358. end;
  359. { TRttiProperty }
  360. TRttiProperty = class(TRttiMember)
  361. private
  362. FPropInfo: PPropInfo;
  363. FAttributesResolved: boolean;
  364. FAttributes: TCustomAttributeArray;
  365. function GetPropertyType: TRttiType;
  366. function GetIsWritable: boolean;
  367. function GetIsReadable: boolean;
  368. protected
  369. function GetVisibility: TMemberVisibility; override;
  370. function GetName: string; override;
  371. function GetHandle: Pointer; override;
  372. public
  373. constructor Create(AParent: TRttiType; APropInfo: PPropInfo);
  374. destructor Destroy; override;
  375. function GetAttributes: TCustomAttributeArray; override;
  376. function GetValue(Instance: pointer): TValue;
  377. procedure SetValue(Instance: pointer; const AValue: TValue);
  378. property PropertyType: TRttiType read GetPropertyType;
  379. property IsReadable: boolean read GetIsReadable;
  380. property IsWritable: boolean read GetIsWritable;
  381. property Visibility: TMemberVisibility read GetVisibility;
  382. end;
  383. TRttiPropertyArray = specialize TArray<TRttiProperty>;
  384. TRttiParameter = class(TRttiNamedObject)
  385. private
  386. FString: String;
  387. protected
  388. function GetParamType: TRttiType; virtual; abstract;
  389. function GetFlags: TParamFlags; virtual; abstract;
  390. public
  391. property ParamType: TRttiType read GetParamType;
  392. property Flags: TParamFlags read GetFlags;
  393. function ToString: String; override;
  394. end;
  395. TRttiParameterArray = specialize TArray<TRttiParameter>;
  396. TMethodImplementationCallbackMethod = procedure(aUserData: Pointer; const aArgs: TValueArray; out aResult: TValue) of object;
  397. TMethodImplementationCallbackProc = procedure(aUserData: Pointer; const aArgs: TValueArray; out aResult: TValue);
  398. TMethodImplementation = class
  399. private
  400. fLowLevelCallback: TFunctionCallCallback;
  401. fCallbackProc: TMethodImplementationCallbackProc;
  402. fCallbackMethod: TMethodImplementationCallbackMethod;
  403. fArgs: specialize TArray<TFunctionCallParameterInfo>;
  404. fArgLen: SizeInt;
  405. fRefArgs: specialize TArray<SizeInt>;
  406. fFlags: TFunctionCallFlags;
  407. fResult: PTypeInfo;
  408. fCC: TCallConv;
  409. procedure InitArgs;
  410. procedure HandleCallback(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer);
  411. constructor Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackMethod);
  412. constructor Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackProc);
  413. Protected
  414. function GetCodeAddress: CodePointer; inline;
  415. public
  416. constructor Create;
  417. destructor Destroy; override;
  418. property CodeAddress: CodePointer read GetCodeAddress;
  419. end;
  420. TRttiInvokableType = class(TRttiType)
  421. protected
  422. function GetParameters(aWithHidden: Boolean): TRttiParameterArray; virtual; abstract;
  423. function GetCallingConvention: TCallConv; virtual; abstract;
  424. function GetReturnType: TRttiType; virtual; abstract;
  425. function GetFlags: TFunctionCallFlags; virtual; abstract;
  426. public type
  427. TCallbackMethod = procedure(aInvokable: TRttiInvokableType; const aArgs: TValueArray; out aResult: TValue) of object;
  428. TCallbackProc = procedure(aInvokable: TRttiInvokableType; const aArgs: TValueArray; out aResult: TValue);
  429. public
  430. function GetParameters: TRttiParameterArray; inline;
  431. property CallingConvention: TCallConv read GetCallingConvention;
  432. property ReturnType: TRttiType read GetReturnType;
  433. function Invoke(const aProcOrMeth: TValue; const aArgs: array of TValue): TValue; virtual; abstract;
  434. { Note: once "reference to" is supported these will be replaced by a single method }
  435. function CreateImplementation(aCallback: TCallbackMethod): TMethodImplementation;
  436. function CreateImplementation(aCallback: TCallbackProc): TMethodImplementation;
  437. function ToString : string; override;
  438. end;
  439. TRttiMethodType = class(TRttiInvokableType)
  440. private
  441. FCallConv: TCallConv;
  442. FReturnType: TRttiType;
  443. FParams, FParamsAll: TRttiParameterArray;
  444. protected
  445. function GetParameters(aWithHidden: Boolean): TRttiParameterArray; override;
  446. function GetCallingConvention: TCallConv; override;
  447. function GetReturnType: TRttiType; override;
  448. function GetFlags: TFunctionCallFlags; override;
  449. public
  450. function Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue; override;
  451. function ToString: string; override;
  452. end;
  453. TRttiProcedureType = class(TRttiInvokableType)
  454. private
  455. FParams, FParamsAll: TRttiParameterArray;
  456. protected
  457. function GetParameters(aWithHidden: Boolean): TRttiParameterArray; override;
  458. function GetCallingConvention: TCallConv; override;
  459. function GetReturnType: TRttiType; override;
  460. function GetFlags: TFunctionCallFlags; override;
  461. public
  462. function Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue; override;
  463. end;
  464. TDispatchKind = (
  465. dkStatic,
  466. dkVtable,
  467. dkDynamic,
  468. dkMessage,
  469. dkInterface,
  470. { the following are FPC-only and will be moved should Delphi add more }
  471. dkMessageString
  472. );
  473. TRttiMethod = class(TRttiMember)
  474. private
  475. FString: String;
  476. function GetFlags: TFunctionCallFlags;
  477. protected
  478. function GetCallingConvention: TCallConv; virtual; abstract;
  479. function GetCodeAddress: CodePointer; virtual; abstract;
  480. function GetDispatchKind: TDispatchKind; virtual; abstract;
  481. function GetHasExtendedInfo: Boolean; virtual;
  482. function GetIsClassMethod: Boolean; virtual; abstract;
  483. function GetIsConstructor: Boolean; virtual; abstract;
  484. function GetIsDestructor: Boolean; virtual; abstract;
  485. function GetIsStatic: Boolean; virtual; abstract;
  486. function GetMethodKind: TMethodKind; virtual; abstract;
  487. function GetReturnType: TRttiType; virtual; abstract;
  488. function GetVirtualIndex: SmallInt; virtual; abstract;
  489. function GetParameters(aWithHidden: Boolean): TRttiParameterArray; virtual; abstract;
  490. public
  491. property CallingConvention: TCallConv read GetCallingConvention;
  492. property CodeAddress: CodePointer read GetCodeAddress;
  493. property DispatchKind: TDispatchKind read GetDispatchKind;
  494. property HasExtendedInfo: Boolean read GetHasExtendedInfo;
  495. property IsClassMethod: Boolean read GetIsClassMethod;
  496. property IsConstructor: Boolean read GetIsConstructor;
  497. property IsDestructor: Boolean read GetIsDestructor;
  498. property IsStatic: Boolean read GetIsStatic;
  499. property MethodKind: TMethodKind read GetMethodKind;
  500. property ReturnType: TRttiType read GetReturnType;
  501. property VirtualIndex: SmallInt read GetVirtualIndex;
  502. function ToString: String; override;
  503. function GetParameters: TRttiParameterArray; inline;
  504. function Invoke(aInstance: TObject; const aArgs: array of TValue): TValue;
  505. function Invoke(aInstance: TClass; const aArgs: array of TValue): TValue;
  506. function Invoke(aInstance: TValue; const aArgs: array of TValue): TValue;
  507. { Note: once "reference to" is supported these will be replaced by a single method }
  508. function CreateImplementation(aUserData: Pointer; aCallback: TMethodImplementationCallbackMethod): TMethodImplementation;
  509. function CreateImplementation(aUserData: Pointer; aCallback: TMethodImplementationCallbackProc): TMethodImplementation;
  510. end;
  511. TRttiStructuredType = class(TRttiType)
  512. end;
  513. TInterfaceType = (
  514. itRefCounted, { aka COM interface }
  515. itRaw { aka CORBA interface }
  516. );
  517. TRttiInterfaceType = class(TRttiType)
  518. private
  519. fDeclaredMethods: specialize TArray<TRttiMethod>;
  520. protected
  521. function IntfMethodCount: Word;
  522. function MethodTable: PIntfMethodTable; virtual; abstract;
  523. function GetBaseType: TRttiType; override;
  524. function GetIntfBaseType: TRttiInterfaceType; virtual; abstract;
  525. function GetDeclaringUnitName: String; virtual; abstract;
  526. function GetGUID: TGUID; virtual; abstract;
  527. function GetGUIDStr: String; virtual;
  528. function GetIntfFlags: TIntfFlags; virtual; abstract;
  529. function GetIntfType: TInterfaceType; virtual; abstract;
  530. public
  531. property BaseType: TRttiInterfaceType read GetIntfBaseType;
  532. property DeclaringUnitName: String read GetDeclaringUnitName;
  533. property GUID: TGUID read GetGUID;
  534. property GUIDStr: String read GetGUIDStr;
  535. property IntfFlags: TIntfFlags read GetIntfFlags;
  536. property IntfType: TInterfaceType read GetIntfType;
  537. function GetDeclaredMethods: specialize TArray<TRttiMethod>; override;
  538. end;
  539. { TRttiInstanceType }
  540. TRttiInstanceType = class(TRttiStructuredType)
  541. private
  542. FPropertiesResolved: Boolean;
  543. FProperties: specialize TArray<TRttiProperty>;
  544. function GetDeclaringUnitName: string;
  545. function GetMetaClassType: TClass;
  546. protected
  547. function GetIsInstance: boolean; override;
  548. function GetTypeSize: integer; override;
  549. function GetBaseType: TRttiType; override;
  550. public
  551. function GetProperties: specialize TArray<TRttiProperty>; override;
  552. property MetaClassType: TClass read GetMetaClassType;
  553. property DeclaringUnitName: string read GetDeclaringUnitName;
  554. end;
  555. TVirtualInterfaceInvokeEvent = procedure(aMethod: TRttiMethod; const aArgs: TValueArray; out aResult: TValue) of object;
  556. TVirtualInterface = class(TInterfacedObject, IInterface)
  557. private
  558. fGUID: TGUID;
  559. fOnInvoke: TVirtualInterfaceInvokeEvent;
  560. fContext: TRttiContext;
  561. fThunks: array[0..2] of CodePointer;
  562. fImpls: array of TMethodImplementation;
  563. fVmt: PCodePointer;
  564. protected
  565. function QueryInterface(constref aIID: TGuid; out aObj): LongInt;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  566. procedure HandleUserCallback(aUserData: Pointer; const aArgs: TValueArray; out aResult: TValue);
  567. public
  568. constructor Create(aPIID: PTypeInfo);
  569. constructor Create(aPIID: PTypeInfo; aInvokeEvent: TVirtualInterfaceInvokeEvent);
  570. destructor Destroy; override;
  571. property OnInvoke: TVirtualInterfaceInvokeEvent read fOnInvoke write fOnInvoke;
  572. end;
  573. ERtti = class(Exception);
  574. EInsufficientRtti = class(ERtti);
  575. EInvocationError = class(ERtti);
  576. ENonPublicType = class(ERtti);
  577. TFunctionCallParameter = record
  578. ValueRef: Pointer;
  579. ValueSize: SizeInt;
  580. Info: TFunctionCallParameterInfo;
  581. end;
  582. TFunctionCallParameterArray = specialize TArray<TFunctionCallParameter>;
  583. TFunctionCallProc = procedure(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer);
  584. TFunctionCallMethod = procedure(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer) of object;
  585. TFunctionCallManager = record
  586. Invoke: procedure(CodeAddress: CodePointer; const Args: TFunctionCallParameterArray; CallingConvention: TCallConv;
  587. ResultType: PTypeInfo; ResultValue: Pointer; Flags: TFunctionCallFlags);
  588. CreateCallbackProc: function(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  589. CreateCallbackMethod: function(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  590. end;
  591. TFunctionCallManagerArray = array[TCallConv] of TFunctionCallManager;
  592. TCallConvSet = set of TCallConv;
  593. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager; out aOldFuncCallMgr: TFunctionCallManager);
  594. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager);
  595. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  596. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager);
  597. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  598. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray);
  599. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  600. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray);
  601. procedure GetFunctionCallManager(aCallConv: TCallConv; out aFuncCallMgr: TFunctionCallManager);
  602. procedure GetFunctionCallManagers(aCallConvs: TCallConvSet; out aFuncCallMgrs: TFunctionCallManagerArray);
  603. procedure GetFunctionCallManagers(out aFuncCallMgrs: TFunctionCallManagerArray);
  604. function Invoke(aCodeAddress: CodePointer; const aArgs: TValueArray; aCallConv: TCallConv;
  605. aResultType: PTypeInfo; aIsStatic: Boolean; aIsConstructor: Boolean): TValue;
  606. function CreateCallbackProc(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  607. function CreateCallbackMethod(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  608. function IsManaged(TypeInfo: PTypeInfo): boolean;
  609. function IsBoolType(ATypeInfo: PTypeInfo): Boolean;
  610. function ArrayOfConstToTValueArray(const aValues: array of const): TValueArray;
  611. {$ifndef InLazIDE}
  612. generic function OpenArrayToDynArrayValue<T>(constref aArray: array of T): TValue;
  613. {$endif}
  614. { these resource strings are needed by units implementing function call managers }
  615. resourcestring
  616. SErrInvokeNotImplemented = 'Invoke functionality is not implemented';
  617. SErrInvokeResultTypeNoValue = 'Function has a result type, but no result pointer provided';
  618. SErrInvokeFailed = 'Invoke call failed';
  619. SErrMethodImplCreateFailed = 'Failed to create method implementation';
  620. SErrCallbackNotImplemented = 'Callback functionality is not implemented';
  621. SErrCallConvNotSupported = 'Calling convention not supported: %s';
  622. SErrTypeKindNotSupported = 'Type kind is not supported: %s';
  623. SErrCallbackHandlerNil = 'Callback handler is Nil';
  624. SErrMissingSelfParam = 'Missing self parameter';
  625. implementation
  626. uses
  627. {$IFDEF FPC_DOTTEDUNITS}
  628. System.Variants,
  629. {$ifdef windows}
  630. WinApi.Windows,
  631. {$endif}
  632. {$ifdef unix}
  633. UnixApi.Base,
  634. {$endif}
  635. System.FGL;
  636. {$ELSE FPC_DOTTEDUNITS}
  637. Variants,
  638. {$ifdef windows}
  639. Windows,
  640. {$endif}
  641. {$ifdef unix}
  642. BaseUnix,
  643. {$endif}
  644. fgl;
  645. {$ENDIF FPC_DOTTEDUNITS}
  646. function AlignToPtr(aPtr: Pointer): Pointer; inline;
  647. begin
  648. {$ifdef CPUM68K}
  649. Result := AlignTypeData(aPtr);
  650. {$else}
  651. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  652. Result := Align(aPtr, SizeOf(Pointer));
  653. {$else}
  654. Result := aPtr;
  655. {$endif}
  656. {$endif}
  657. end;
  658. type
  659. { TRttiPool }
  660. TRttiPool = class
  661. private type
  662. TRttiObjectMap = specialize TFPGMap<Pointer, TRttiObject>;
  663. private
  664. FObjectMap: TRttiObjectMap;
  665. FTypesList: specialize TArray<TRttiType>;
  666. FTypeCount: LongInt;
  667. FLock: TRTLCriticalSection;
  668. public
  669. function GetTypes: specialize TArray<TRttiType>;
  670. function GetType(ATypeInfo: PTypeInfo): TRttiType;
  671. function GetByHandle(aHandle: Pointer): TRttiObject;
  672. procedure AddObject(aObject: TRttiObject);
  673. constructor Create;
  674. destructor Destroy; override;
  675. end;
  676. IPooltoken = interface
  677. ['{3CDB3CE9-AB55-CBAA-7B9D-2F3BB1CF5AF8}']
  678. function RttiPool: TRttiPool;
  679. end;
  680. { TPoolToken }
  681. TPoolToken = class(TInterfacedObject, IPooltoken)
  682. public
  683. constructor Create;
  684. destructor Destroy; override;
  685. function RttiPool: TRttiPool;
  686. end;
  687. { TValueDataIntImpl }
  688. TValueDataIntImpl = class(TInterfacedObject, IValueData)
  689. private
  690. FBuffer: Pointer;
  691. FDataSize: SizeInt;
  692. FTypeInfo: PTypeInfo;
  693. FIsCopy: Boolean;
  694. FUseAddRef: Boolean;
  695. public
  696. constructor CreateCopy(ACopyFromBuffer: Pointer; ALen: SizeInt; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  697. constructor CreateRef(AData: Pointer; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  698. destructor Destroy; override;
  699. procedure ExtractRawData(ABuffer: pointer);
  700. procedure ExtractRawDataNoCopy(ABuffer: pointer);
  701. function GetDataSize: SizeInt;
  702. function GetReferenceToRawData: pointer;
  703. end;
  704. TRttiRefCountedInterfaceType = class(TRttiInterfaceType)
  705. private
  706. function IntfData: PInterfaceData; inline;
  707. protected
  708. function MethodTable: PIntfMethodTable; override;
  709. function GetIntfBaseType: TRttiInterfaceType; override;
  710. function GetDeclaringUnitName: String; override;
  711. function GetGUID: TGUID; override;
  712. function GetIntfFlags: TIntfFlags; override;
  713. function GetIntfType: TInterfaceType; override;
  714. end;
  715. TRttiRawInterfaceType = class(TRttiInterfaceType)
  716. private
  717. function IntfData: PInterfaceRawData; inline;
  718. protected
  719. function MethodTable: PIntfMethodTable; override;
  720. function GetIntfBaseType: TRttiInterfaceType; override;
  721. function GetDeclaringUnitName: String; override;
  722. function GetGUID: TGUID; override;
  723. function GetGUIDStr: String; override;
  724. function GetIntfFlags: TIntfFlags; override;
  725. function GetIntfType: TInterfaceType; override;
  726. end;
  727. TRttiVmtMethodParameter = class(TRttiParameter)
  728. private
  729. FVmtMethodParam: PVmtMethodParam;
  730. protected
  731. function GetHandle: Pointer; override;
  732. function GetName: String; override;
  733. function GetFlags: TParamFlags; override;
  734. function GetParamType: TRttiType; override;
  735. public
  736. constructor Create(AVmtMethodParam: PVmtMethodParam);
  737. end;
  738. TRttiMethodTypeParameter = class(TRttiParameter)
  739. private
  740. fHandle: Pointer;
  741. fName: String;
  742. fFlags: TParamFlags;
  743. fType: PTypeInfo;
  744. protected
  745. function GetHandle: Pointer; override;
  746. function GetName: String; override;
  747. function GetFlags: TParamFlags; override;
  748. function GetParamType: TRttiType; override;
  749. public
  750. constructor Create(aHandle: Pointer; const aName: String; aFlags: TParamFlags; aType: PTypeInfo);
  751. end;
  752. TRttiIntfMethod = class(TRttiMethod)
  753. private
  754. FIntfMethodEntry: PIntfMethodEntry;
  755. FIndex: SmallInt;
  756. FParams, FParamsAll: TRttiParameterArray;
  757. protected
  758. function GetHandle: Pointer; override;
  759. function GetName: String; override;
  760. function GetCallingConvention: TCallConv; override;
  761. function GetCodeAddress: CodePointer; override;
  762. function GetDispatchKind: TDispatchKind; override;
  763. function GetHasExtendedInfo: Boolean; override;
  764. function GetIsClassMethod: Boolean; override;
  765. function GetIsConstructor: Boolean; override;
  766. function GetIsDestructor: Boolean; override;
  767. function GetIsStatic: Boolean; override;
  768. function GetMethodKind: TMethodKind; override;
  769. function GetReturnType: TRttiType; override;
  770. function GetVirtualIndex: SmallInt; override;
  771. function GetParameters(aWithHidden: Boolean): TRttiParameterArray; override;
  772. public
  773. constructor Create(AParent: TRttiType; AIntfMethodEntry: PIntfMethodEntry; AIndex: SmallInt);
  774. end;
  775. resourcestring
  776. SErrUnableToGetValueForType = 'Unable to get value for type %s';
  777. SErrUnableToSetValueForType = 'Unable to set value for type %s';
  778. SErrDimensionOutOfRange = 'Dimension index %d is out of range [0, %d[';
  779. SErrLengthOfArrayMismatch = 'Length of static array does not match: Got %d, but expected %d';
  780. SErrInvalidTypecast = 'Invalid class typecast';
  781. SErrRttiObjectNoHandle = 'RTTI object instance has no valid handle property';
  782. SErrRttiObjectAlreadyRegistered = 'A RTTI object with handle 0x%x is already registered';
  783. SErrInvokeInsufficientRtti = 'Insufficient RTTI to invoke function';
  784. SErrInvokeStaticNoSelf = 'Static function must not be called with in an instance: %s';
  785. SErrInvokeNotStaticNeedsSelf = 'Non static function must be called with an instance: %s';
  786. SErrInvokeClassMethodClassSelf = 'Class method needs to be called with a class type: %s';
  787. SErrInvokeArrayArgExpected = 'Array argument expected for parameter %s of method %s';
  788. SErrInvokeArgInvalidType = 'Invalid type of argument for parameter %s of method %s';
  789. SErrInvokeArgCount = 'Invalid argument count for method %s; expected %d, but got %d';
  790. SErrInvokeNoCodeAddr = 'Failed to determine code address for method: %s';
  791. SErrInvokeRttiDataError = 'The RTTI data is inconsistent for method: %s';
  792. SErrInvokeCallableNotProc = 'The callable value is not a procedure variable for: %s';
  793. SErrInvokeCallableNotMethod = 'The callable value is not a method variable for: %s';
  794. SErrMethodImplNoCallback = 'No callback specified for method implementation';
  795. SErrMethodImplInsufficientRtti = 'Insufficient RTTI to create method implementation';
  796. SErrMethodImplCreateNoArg = 'TMethodImplementation can not be created this way';
  797. SErrVirtIntfTypeNil = 'No type information provided for TVirtualInterface';
  798. SErrVirtIntfTypeMustBeIntf = 'Type ''%s'' is not an interface type';
  799. SErrVirtIntfTypeNotFound = 'Type ''%s'' is not valid';
  800. SErrVirtIntfNotAllMethodsRTTI = 'Not all methods of ''%s'' or its parents have the required RTTI';
  801. SErrVirtIntfRetrieveIInterface = 'Failed to retrieve IInterface information';
  802. SErrVirtIntfCreateThunk = 'Failed to create thunks for ''%0:s''';
  803. SErrVirtIntfCreateImpl = 'Failed to create implementation for method ''%1:s'' of ''%0:s''';
  804. SErrVirtIntfInvalidVirtIdx = 'Virtual index %2:d for method ''%1:s'' of ''%0:s'' is invalid';
  805. SErrVirtIntfMethodNil = 'Method %1:d of ''%0:s'' is Nil';
  806. SErrVirtIntfCreateVmt = 'Failed to create VMT for ''%s''';
  807. SErrVirtIntfIInterface = 'Failed to prepare IInterface method callbacks';
  808. var
  809. PoolRefCount : integer;
  810. GRttiPool : TRttiPool;
  811. FuncCallMgr: TFunctionCallManagerArray;
  812. function AllocateMemory(aSize: PtrUInt): Pointer;
  813. begin
  814. {$IF DEFINED(WINDOWS)}
  815. Result := VirtualAlloc(Nil, aSize, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
  816. {$ELSEIF DEFINED(UNIX)}
  817. Result := fpmmap(Nil, aSize, PROT_READ or PROT_WRITE, MAP_PRIVATE or MAP_ANONYMOUS, 0, 0);
  818. {$ELSE}
  819. Result := Nil;
  820. {$ENDIF}
  821. end;
  822. function ProtectMemory(aPtr: Pointer; aSize: PtrUInt; aExecutable: Boolean): Boolean;
  823. {$IF DEFINED(WINDOWS)}
  824. var
  825. oldprot: DWORD;
  826. {$ENDIF}
  827. begin
  828. {$IF DEFINED(WINDOWS)}
  829. if aExecutable then
  830. Result := VirtualProtect(aPtr, aSize, PAGE_EXECUTE_READ, oldprot)
  831. else
  832. Result := VirtualProtect(aPtr, aSize, PAGE_READWRITE, oldprot);
  833. {$ELSEIF DEFINED(UNIX)}
  834. if aExecutable then
  835. Result := Fpmprotect(aPtr, aSize, PROT_EXEC or PROT_READ) = 0
  836. else
  837. Result := Fpmprotect(aPtr, aSize, PROT_READ or PROT_WRITE) = 0;
  838. {$ELSE}
  839. Result := False;
  840. {$ENDIF}
  841. end;
  842. procedure FreeMemory(aPtr: Pointer; aSize: PtrUInt);
  843. begin
  844. {$IF DEFINED(WINDOWS)}
  845. VirtualFree(aPtr, 0, MEM_RELEASE);
  846. {$ELSEIF DEFINED(UNIX)}
  847. fpmunmap(aPtr, aSize);
  848. {$ELSE}
  849. { nothing }
  850. {$ENDIF}
  851. end;
  852. label
  853. RawThunkEnd;
  854. {$if defined(cpui386)}
  855. const
  856. RawThunkPlaceholderBytesToPop = $12341234;
  857. RawThunkPlaceholderProc = $87658765;
  858. RawThunkPlaceholderContext = $43214321;
  859. type
  860. TRawThunkBytesToPop = UInt32;
  861. TRawThunkProc = PtrUInt;
  862. TRawThunkContext = PtrUInt;
  863. { works for both cdecl and stdcall }
  864. procedure RawThunk; assembler; nostackframe;
  865. asm
  866. { the stack layout is
  867. $ReturnAddr <- ESP
  868. ArgN
  869. ArgN - 1
  870. ...
  871. Arg1
  872. Arg0
  873. aBytesToPop is the size of the stack to the Self argument }
  874. movl RawThunkPlaceholderBytesToPop, %eax
  875. movl %esp, %ecx
  876. lea (%ecx,%eax), %eax
  877. movl RawThunkPlaceholderContext, (%eax)
  878. movl RawThunkPlaceholderProc, %eax
  879. jmp %eax
  880. RawThunkEnd:
  881. end;
  882. {$elseif defined(cpux86_64)}
  883. const
  884. RawThunkPlaceholderProc = PtrUInt($8765876587658765);
  885. RawThunkPlaceholderContext = PtrUInt($4321432143214321);
  886. type
  887. TRawThunkProc = PtrUInt;
  888. TRawThunkContext = PtrUInt;
  889. {$ifdef win64}
  890. procedure RawThunk; assembler; nostackframe;
  891. asm
  892. { Self is always in register RCX }
  893. movq RawThunkPlaceholderContext, %rcx
  894. movq RawThunkPlaceholderProc, %rax
  895. jmp %rax
  896. RawThunkEnd:
  897. end;
  898. {$else}
  899. procedure RawThunk; assembler; nostackframe;
  900. asm
  901. { Self is always in register RDI }
  902. movq RawThunkPlaceholderContext, %rdi
  903. movq RawThunkPlaceholderProc, %rax
  904. jmp %rax
  905. RawThunkEnd:
  906. end;
  907. {$endif}
  908. {$elseif defined(cpuarm)}
  909. const
  910. RawThunkPlaceholderProc = $87658765;
  911. RawThunkPlaceholderContext = $43214321;
  912. type
  913. TRawThunkProc = PtrUInt;
  914. TRawThunkContext = PtrUInt;
  915. procedure RawThunk; assembler; nostackframe;
  916. asm
  917. (* To be compatible with Thumb we first load the function pointer into R0,
  918. then move that to R12 which is volatile and then we load the new Self into
  919. R0 *)
  920. ldr r0, .LProc
  921. mov r12, r0
  922. ldr r0, .LContext
  923. {$ifdef CPUARM_HAS_BX}
  924. bx r12
  925. {$else}
  926. mov pc, r12
  927. {$endif}
  928. .LProc:
  929. .long RawThunkPlaceholderProc
  930. .LContext:
  931. .long RawThunkPlaceholderContext
  932. RawThunkEnd:
  933. end;
  934. {$elseif defined(cpuaarch64)}
  935. const
  936. RawThunkPlaceholderProc = $8765876587658765;
  937. RawThunkPlaceholderContext = $4321432143214321;
  938. type
  939. TRawThunkProc = PtrUInt;
  940. TRawThunkContext = PtrUInt;
  941. procedure RawThunk; assembler; nostackframe;
  942. asm
  943. ldr x16, .LProc
  944. ldr x0, .LContext
  945. br x16
  946. .LProc:
  947. .quad RawThunkPlaceholderProc
  948. .LContext:
  949. .quad RawThunkPlaceholderContext
  950. RawThunkEnd:
  951. end;
  952. {$elseif defined(cpum68k)}
  953. const
  954. RawThunkPlaceholderProc = $87658765;
  955. RawThunkPlaceholderContext = $43214321;
  956. type
  957. TRawThunkProc = PtrUInt;
  958. TRawThunkContext = PtrUInt;
  959. procedure RawThunk; assembler; nostackframe;
  960. asm
  961. lea 4(sp), a0
  962. move.l #RawThunkPlaceholderContext, (a0)
  963. move.l #RawThunkPlaceholderProc, a0
  964. jmp (a0)
  965. RawThunkEnd:
  966. end;
  967. {$elseif defined(cpuriscv64)}
  968. const
  969. RawThunkPlaceholderProc = $8765876587658765;
  970. RawThunkPlaceholderContext = $4321432143214321;
  971. type
  972. TRawThunkProc = PtrUInt;
  973. TRawThunkContext = PtrUInt;
  974. procedure RawThunk; assembler; nostackframe;
  975. asm
  976. ld x5, .LProc
  977. ld x10, .LContext
  978. jalr x0, x5, 0
  979. .LProc:
  980. .quad RawThunkPlaceholderProc
  981. .LContext:
  982. .quad RawThunkPlaceholderContext
  983. RawThunkEnd:
  984. end;
  985. {$elseif defined(cpuriscv32)}
  986. const
  987. RawThunkPlaceholderProc = $87658765;
  988. RawThunkPlaceholderContext = $43214321;
  989. type
  990. TRawThunkProc = PtrUInt;
  991. TRawThunkContext = PtrUInt;
  992. procedure RawThunk; assembler; nostackframe;
  993. asm
  994. lw x5, .LProc
  995. lw x10, .LContext
  996. jalr x0, x5, 0
  997. .LProc:
  998. .long RawThunkPlaceholderProc
  999. .LContext:
  1000. .long RawThunkPlaceholderContext
  1001. RawThunkEnd:
  1002. end;
  1003. {$elseif defined(cpuloongarch64)}
  1004. const
  1005. RawThunkPlaceholderProc = $8765876587658765;
  1006. RawThunkPlaceholderContext = $4321432143214321;
  1007. type
  1008. TRawThunkProc = PtrUInt;
  1009. TRawThunkContext = PtrUInt;
  1010. procedure RawThunk; assembler; nostackframe;
  1011. asm
  1012. move $t0, $ra
  1013. bl .Lreal
  1014. .quad RawThunkPlaceholderProc
  1015. .quad RawThunkPlaceholderContext
  1016. .Lreal:
  1017. ld.d $a0, $ra, 8
  1018. ld.d $t1, $ra, 0
  1019. move $ra, $t0
  1020. jr $t1
  1021. RawThunkEnd:
  1022. end;
  1023. {$endif}
  1024. {$if declared(RawThunk)}
  1025. const
  1026. RawThunkEndPtr: Pointer = @RawThunkEnd;
  1027. type
  1028. {$if declared(TRawThunkBytesToPop)}
  1029. PRawThunkBytesToPop = ^TRawThunkBytesToPop;
  1030. {$endif}
  1031. PRawThunkContext = ^TRawThunkContext;
  1032. PRawThunkProc = ^TRawThunkProc;
  1033. {$endif}
  1034. { Delphi has these as part of TRawVirtualClass.TVTable; until we have that we
  1035. simply leave that here in the implementation }
  1036. function AllocateRawThunk(aProc: CodePointer; aContext: Pointer; aBytesToPop: SizeInt): CodePointer;
  1037. {$if declared(RawThunk)}
  1038. var
  1039. size, i: SizeInt;
  1040. {$if declared(TRawThunkBytesToPop)}
  1041. btp: PRawThunkBytesToPop;
  1042. btpdone: Boolean;
  1043. {$endif}
  1044. context: PRawThunkContext;
  1045. contextdone: Boolean;
  1046. proc: PRawThunkProc;
  1047. procdone: Boolean;
  1048. {$endif}
  1049. begin
  1050. {$if not declared(RawThunk)}
  1051. { platform dose not have thunk support... :/ }
  1052. Result := Nil;
  1053. {$else}
  1054. Size := PtrUInt(RawThunkEndPtr) - PtrUInt(@RawThunk) + 1;
  1055. Result := AllocateMemory(size);
  1056. Move(Pointer(@RawThunk)^, Result^, size);
  1057. {$if declared(TRawThunkBytesToPop)}
  1058. btpdone := False;
  1059. {$endif}
  1060. contextdone := False;
  1061. procdone := False;
  1062. for i := 0 to Size - 1 do begin
  1063. {$if declared(TRawThunkBytesToPop)}
  1064. if not btpdone and (i <= Size - SizeOf(TRawThunkBytesToPop)) then begin
  1065. btp := PRawThunkBytesToPop(PByte(Result) + i);
  1066. if btp^ = TRawThunkBytesToPop(RawThunkPlaceholderBytesToPop) then begin
  1067. btp^ := TRawThunkBytesToPop(aBytesToPop);
  1068. btpdone := True;
  1069. end;
  1070. end;
  1071. {$endif}
  1072. if not contextdone and (i <= Size - SizeOf(TRawThunkContext)) then begin
  1073. context := PRawThunkContext(PByte(Result) + i);
  1074. if context^ = TRawThunkContext(RawThunkPlaceholderContext) then begin
  1075. context^ := TRawThunkContext(aContext);
  1076. contextdone := True;
  1077. end;
  1078. end;
  1079. if not procdone and (i <= Size - SizeOf(TRawThunkProc)) then begin
  1080. proc := PRawThunkProc(PByte(Result) + i);
  1081. if proc^ = TRawThunkProc(RawThunkPlaceholderProc) then begin
  1082. proc^ := TRawThunkProc(aProc);
  1083. procdone := True;
  1084. end;
  1085. end;
  1086. end;
  1087. if not contextdone or not procdone
  1088. {$if declared(TRawThunkBytesToPop)}
  1089. or not btpdone
  1090. {$endif}
  1091. then begin
  1092. FreeMemory(Result, Size);
  1093. Result := Nil;
  1094. end else
  1095. ProtectMemory(Result, Size, True);
  1096. {$endif}
  1097. end;
  1098. procedure FreeRawThunk(aThunk: CodePointer);
  1099. begin
  1100. {$if declared(RawThunk)}
  1101. FreeMemory(aThunk, PtrUInt(RawThunkEndPtr) - PtrUInt(@RawThunk));
  1102. {$endif}
  1103. end;
  1104. function CCToStr(aCC: TCallConv): String; inline;
  1105. begin
  1106. WriteStr(Result, aCC);
  1107. end;
  1108. procedure NoInvoke(aCodeAddress: CodePointer; const aArgs: TFunctionCallParameterArray; aCallConv: TCallConv;
  1109. aResultType: PTypeInfo; aResultValue: Pointer; aFlags: TFunctionCallFlags);
  1110. begin
  1111. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  1112. end;
  1113. function NoCreateCallbackProc(aFunc: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  1114. begin
  1115. Result := Nil;
  1116. raise ENotImplemented.Create(SErrCallbackNotImplemented);
  1117. end;
  1118. function NoCreateCallbackMethod(aFunc: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  1119. begin
  1120. Result := Nil;
  1121. raise ENotImplemented.Create(SErrCallbackNotImplemented);
  1122. end;
  1123. const
  1124. NoFunctionCallManager: TFunctionCallManager = (
  1125. Invoke: @NoInvoke;
  1126. CreateCallbackProc: @NoCreateCallbackProc;
  1127. CreateCallbackMethod: @NoCreateCallbackMethod;
  1128. );
  1129. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager;
  1130. out aOldFuncCallMgr: TFunctionCallManager);
  1131. begin
  1132. aOldFuncCallMgr := FuncCallMgr[aCallConv];
  1133. FuncCallMgr[aCallConv] := aFuncCallMgr;
  1134. end;
  1135. procedure SetFunctionCallManager(aCallConv: TCallConv; constref aFuncCallMgr: TFunctionCallManager);
  1136. var
  1137. dummy: TFunctionCallManager;
  1138. begin
  1139. SetFunctionCallManager(aCallConv, aFuncCallMgr, dummy);
  1140. end;
  1141. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager;
  1142. out aOldFuncCallMgrs: TFunctionCallManagerArray);
  1143. var
  1144. cc: TCallConv;
  1145. begin
  1146. for cc := Low(TCallConv) to High(TCallConv) do
  1147. if cc in aCallConvs then begin
  1148. aOldFuncCallMgrs[cc] := FuncCallMgr[cc];
  1149. FuncCallMgr[cc] := aFuncCallMgr;
  1150. end else
  1151. aOldFuncCallMgrs[cc] := Default(TFunctionCallManager);
  1152. end;
  1153. procedure SetFunctionCallManager(aCallConvs: TCallConvSet; constref aFuncCallMgr: TFunctionCallManager);
  1154. var
  1155. dummy: TFunctionCallManagerArray;
  1156. begin
  1157. SetFunctionCallManager(aCallConvs, aFuncCallMgr, dummy);
  1158. end;
  1159. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  1160. var
  1161. cc: TCallConv;
  1162. begin
  1163. for cc := Low(TCallConv) to High(TCallConv) do
  1164. if cc in aCallConvs then begin
  1165. aOldFuncCallMgrs[cc] := FuncCallMgr[cc];
  1166. FuncCallMgr[cc] := aFuncCallMgrs[cc];
  1167. end else
  1168. aOldFuncCallMgrs[cc] := Default(TFunctionCallManager);
  1169. end;
  1170. procedure SetFunctionCallManagers(aCallConvs: TCallConvSet; constref aFuncCallMgrs: TFunctionCallManagerArray);
  1171. var
  1172. dummy: TFunctionCallManagerArray;
  1173. begin
  1174. SetFunctionCallManagers(aCallConvs, aFuncCallMgrs, dummy);
  1175. end;
  1176. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray; out aOldFuncCallMgrs: TFunctionCallManagerArray);
  1177. begin
  1178. aOldFuncCallMgrs := FuncCallMgr;
  1179. FuncCallMgr := aFuncCallMgrs;
  1180. end;
  1181. procedure SetFunctionCallManagers(constref aFuncCallMgrs: TFunctionCallManagerArray);
  1182. var
  1183. dummy: TFunctionCallManagerArray;
  1184. begin
  1185. SetFunctionCallManagers(aFuncCallMgrs, dummy);
  1186. end;
  1187. procedure GetFunctionCallManager(aCallConv: TCallConv; out aFuncCallMgr: TFunctionCallManager);
  1188. begin
  1189. aFuncCallMgr := FuncCallMgr[aCallConv];
  1190. end;
  1191. procedure GetFunctionCallManagers(aCallConvs: TCallConvSet; out aFuncCallMgrs: TFunctionCallManagerArray);
  1192. var
  1193. cc: TCallConv;
  1194. begin
  1195. for cc := Low(TCallConv) to High(TCallConv) do
  1196. if cc in aCallConvs then
  1197. aFuncCallMgrs[cc] := FuncCallMgr[cc]
  1198. else
  1199. aFuncCallMgrs[cc] := Default(TFunctionCallManager);
  1200. end;
  1201. procedure GetFunctionCallManagers(out aFuncCallMgrs: TFunctionCallManagerArray);
  1202. begin
  1203. aFuncCallMgrs := FuncCallMgr;
  1204. end;
  1205. procedure InitDefaultFunctionCallManager;
  1206. var
  1207. cc: TCallConv;
  1208. begin
  1209. for cc := Low(TCallConv) to High(TCallConv) do
  1210. FuncCallMgr[cc] := NoFunctionCallManager;
  1211. end;
  1212. { TRttiPool }
  1213. function TRttiPool.GetTypes: specialize TArray<TRttiType>;
  1214. begin
  1215. if not Assigned(FTypesList) then
  1216. Exit(Nil);
  1217. {$ifdef FPC_HAS_FEATURE_THREADING}
  1218. EnterCriticalsection(FLock);
  1219. try
  1220. {$endif}
  1221. Result := Copy(FTypesList, 0, FTypeCount);
  1222. {$ifdef FPC_HAS_FEATURE_THREADING}
  1223. finally
  1224. LeaveCriticalsection(FLock);
  1225. end;
  1226. {$endif}
  1227. end;
  1228. function TRttiPool.GetType(ATypeInfo: PTypeInfo): TRttiType;
  1229. var
  1230. obj: TRttiObject;
  1231. begin
  1232. if not Assigned(ATypeInfo) then
  1233. Exit(Nil);
  1234. {$ifdef FPC_HAS_FEATURE_THREADING}
  1235. EnterCriticalsection(FLock);
  1236. try
  1237. {$endif}
  1238. Result := Nil;
  1239. obj := GetByHandle(ATypeInfo);
  1240. if Assigned(obj) then
  1241. Result := obj as TRttiType;
  1242. if not Assigned(Result) then
  1243. begin
  1244. if FTypeCount = Length(FTypesList) then
  1245. begin
  1246. SetLength(FTypesList, FTypeCount * 2);
  1247. end;
  1248. case ATypeInfo^.Kind of
  1249. tkClass : Result := TRttiInstanceType.Create(ATypeInfo);
  1250. tkInterface: Result := TRttiRefCountedInterfaceType.Create(ATypeInfo);
  1251. tkInterfaceRaw: Result := TRttiRawInterfaceType.Create(ATypeInfo);
  1252. tkArray: Result := TRttiArrayType.Create(ATypeInfo);
  1253. tkDynArray: Result := TRttiDynamicArrayType.Create(ATypeInfo);
  1254. tkInt64,
  1255. tkQWord: Result := TRttiInt64Type.Create(ATypeInfo);
  1256. tkInteger,
  1257. tkChar,
  1258. tkWChar: Result := TRttiOrdinalType.Create(ATypeInfo);
  1259. tkSString,
  1260. tkLString,
  1261. tkAString,
  1262. tkUString,
  1263. tkWString : Result := TRttiStringType.Create(ATypeInfo);
  1264. tkFloat : Result := TRttiFloatType.Create(ATypeInfo);
  1265. tkPointer : Result := TRttiPointerType.Create(ATypeInfo);
  1266. tkProcVar : Result := TRttiProcedureType.Create(ATypeInfo);
  1267. tkMethod : Result := TRttiMethodType.Create(ATypeInfo);
  1268. else
  1269. Result := TRttiType.Create(ATypeInfo);
  1270. end;
  1271. FTypesList[FTypeCount] := Result;
  1272. FObjectMap.Add(ATypeInfo, Result);
  1273. Inc(FTypeCount);
  1274. end;
  1275. {$ifdef FPC_HAS_FEATURE_THREADING}
  1276. finally
  1277. LeaveCriticalsection(FLock);
  1278. end;
  1279. {$endif}
  1280. end;
  1281. function TRttiPool.GetByHandle(aHandle: Pointer): TRttiObject;
  1282. var
  1283. idx: LongInt;
  1284. begin
  1285. if not Assigned(aHandle) then
  1286. Exit(Nil);
  1287. {$ifdef FPC_HAS_FEATURE_THREADING}
  1288. EnterCriticalsection(FLock);
  1289. try
  1290. {$endif}
  1291. idx := FObjectMap.IndexOf(aHandle);
  1292. if idx < 0 then
  1293. Result := Nil
  1294. else
  1295. Result := FObjectMap.Data[idx];
  1296. {$ifdef FPC_HAS_FEATURE_THREADING}
  1297. finally
  1298. LeaveCriticalsection(FLock);
  1299. end;
  1300. {$endif}
  1301. end;
  1302. procedure TRttiPool.AddObject(aObject: TRttiObject);
  1303. var
  1304. idx: LongInt;
  1305. begin
  1306. if not Assigned(aObject) then
  1307. Exit;
  1308. if not Assigned(aObject.Handle) then
  1309. raise EArgumentException.Create(SErrRttiObjectNoHandle);
  1310. {$ifdef FPC_HAS_FEATURE_THREADING}
  1311. EnterCriticalsection(FLock);
  1312. try
  1313. {$endif}
  1314. idx := FObjectMap.IndexOf(aObject.Handle);
  1315. if idx < 0 then
  1316. FObjectMap.Add(aObject.Handle, aObject)
  1317. else if FObjectMap.Data[idx] <> aObject then
  1318. raise EInvalidOpException.CreateFmt(SErrRttiObjectAlreadyRegistered, [aObject.Handle]);
  1319. {$ifdef FPC_HAS_FEATURE_THREADING}
  1320. finally
  1321. LeaveCriticalsection(FLock);
  1322. end;
  1323. {$endif}
  1324. end;
  1325. constructor TRttiPool.Create;
  1326. begin
  1327. {$ifdef FPC_HAS_FEATURE_THREADING}
  1328. InitCriticalSection(FLock);
  1329. {$endif}
  1330. SetLength(FTypesList, 32);
  1331. FObjectMap := TRttiObjectMap.Create;
  1332. end;
  1333. destructor TRttiPool.Destroy;
  1334. var
  1335. i: LongInt;
  1336. begin
  1337. for i := 0 to FObjectMap.Count - 1 do
  1338. FObjectMap.Data[i].Free;
  1339. FObjectMap.Free;
  1340. {$ifdef FPC_HAS_FEATURE_THREADING}
  1341. DoneCriticalsection(FLock);
  1342. {$endif}
  1343. inherited Destroy;
  1344. end;
  1345. { TPoolToken }
  1346. constructor TPoolToken.Create;
  1347. begin
  1348. inherited Create;
  1349. if InterlockedIncrement(PoolRefCount)=1 then
  1350. GRttiPool := TRttiPool.Create;
  1351. end;
  1352. destructor TPoolToken.Destroy;
  1353. begin
  1354. if InterlockedDecrement(PoolRefCount)=0 then
  1355. GRttiPool.Free;
  1356. inherited;
  1357. end;
  1358. function TPoolToken.RttiPool: TRttiPool;
  1359. begin
  1360. result := GRttiPool;
  1361. end;
  1362. { TValueDataIntImpl }
  1363. procedure IntFinalize(APointer, ATypeInfo: Pointer);
  1364. external name 'FPC_FINALIZE';
  1365. procedure IntInitialize(APointer, ATypeInfo: Pointer);
  1366. external name 'FPC_INITIALIZE';
  1367. procedure IntAddRef(APointer, ATypeInfo: Pointer);
  1368. external name 'FPC_ADDREF';
  1369. function IntCopy(ASource, ADest, ATypeInfo: Pointer): SizeInt;
  1370. external name 'FPC_COPY';
  1371. constructor TValueDataIntImpl.CreateCopy(ACopyFromBuffer: Pointer; ALen: SizeInt; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  1372. begin
  1373. FTypeInfo := ATypeInfo;
  1374. FDataSize:=ALen;
  1375. if ALen>0 then
  1376. begin
  1377. Getmem(FBuffer,FDataSize);
  1378. if Assigned(ACopyFromBuffer) then
  1379. system.move(ACopyFromBuffer^,FBuffer^,FDataSize)
  1380. else
  1381. FillChar(FBuffer^, FDataSize, 0);
  1382. end;
  1383. FIsCopy := True;
  1384. FUseAddRef := AAddRef;
  1385. if AAddRef and (ALen > 0) then begin
  1386. if Assigned(ACopyFromBuffer) then
  1387. IntAddRef(FBuffer, FTypeInfo)
  1388. else
  1389. IntInitialize(FBuffer, FTypeInfo);
  1390. end;
  1391. end;
  1392. constructor TValueDataIntImpl.CreateRef(AData: Pointer; ATypeInfo: PTypeInfo; AAddRef: Boolean);
  1393. begin
  1394. FTypeInfo := ATypeInfo;
  1395. FDataSize := SizeOf(Pointer);
  1396. if Assigned(AData) then
  1397. FBuffer := PPointer(AData)^
  1398. else
  1399. FBuffer := Nil;
  1400. FIsCopy := False;
  1401. FUseAddRef := AAddRef;
  1402. if AAddRef and Assigned(AData) then
  1403. IntAddRef(@FBuffer, FTypeInfo);
  1404. end;
  1405. destructor TValueDataIntImpl.Destroy;
  1406. begin
  1407. if Assigned(FBuffer) then begin
  1408. if FUseAddRef then
  1409. if FIsCopy then
  1410. IntFinalize(FBuffer, FTypeInfo)
  1411. else
  1412. IntFinalize(@FBuffer, FTypeInfo);
  1413. if FIsCopy then
  1414. Freemem(FBuffer);
  1415. end;
  1416. inherited Destroy;
  1417. end;
  1418. procedure TValueDataIntImpl.ExtractRawData(ABuffer: pointer);
  1419. begin
  1420. if FDataSize = 0 then
  1421. Exit;
  1422. if FIsCopy then
  1423. System.Move(FBuffer^, ABuffer^, FDataSize)
  1424. else
  1425. System.Move(FBuffer{!}, ABuffer^, FDataSize);
  1426. if FUseAddRef then
  1427. IntAddRef(ABuffer, FTypeInfo);
  1428. end;
  1429. procedure TValueDataIntImpl.ExtractRawDataNoCopy(ABuffer: pointer);
  1430. begin
  1431. if FDataSize = 0 then
  1432. Exit;
  1433. if FIsCopy then
  1434. system.move(FBuffer^, ABuffer^, FDataSize)
  1435. else
  1436. System.Move(FBuffer{!}, ABuffer^, FDataSize);
  1437. end;
  1438. function TValueDataIntImpl.GetDataSize: SizeInt;
  1439. begin
  1440. result := FDataSize;
  1441. end;
  1442. function TValueDataIntImpl.GetReferenceToRawData: pointer;
  1443. begin
  1444. if FIsCopy then
  1445. result := FBuffer
  1446. else
  1447. result := @FBuffer;
  1448. end;
  1449. { TValue }
  1450. procedure TValue.Init;
  1451. begin
  1452. { resets the whole variant part; FValueData is already Nil }
  1453. {$if SizeOf(TMethod) > SizeOf(QWord)}
  1454. FData.FAsMethod.Code := Nil;
  1455. FData.FAsMethod.Data := Nil;
  1456. {$else}
  1457. FData.FAsUInt64 := 0;
  1458. {$endif}
  1459. end;
  1460. class function TValue.Empty: TValue;
  1461. begin
  1462. Result.Init;
  1463. result.FData.FTypeInfo := nil;
  1464. end;
  1465. function TValue.GetTypeDataProp: PTypeData;
  1466. begin
  1467. result := GetTypeData(FData.FTypeInfo);
  1468. end;
  1469. function TValue.GetTypeInfo: PTypeInfo;
  1470. begin
  1471. result := FData.FTypeInfo;
  1472. end;
  1473. function TValue.GetTypeKind: TTypeKind;
  1474. begin
  1475. if not Assigned(FData.FTypeInfo) then
  1476. Result := tkUnknown
  1477. else
  1478. result := FData.FTypeInfo^.Kind;
  1479. end;
  1480. function TValue.GetDataSize: SizeInt;
  1481. begin
  1482. if Assigned(FData.FValueData) and (Kind <> tkSString) then
  1483. Result := FData.FValueData.GetDataSize
  1484. else begin
  1485. Result := 0;
  1486. case Kind of
  1487. tkEnumeration,
  1488. tkBool,
  1489. tkInt64,
  1490. tkQWord,
  1491. tkInteger:
  1492. case TypeData^.OrdType of
  1493. otSByte,
  1494. otUByte:
  1495. Result := SizeOf(Byte);
  1496. otSWord,
  1497. otUWord:
  1498. Result := SizeOf(Word);
  1499. otSLong,
  1500. otULong:
  1501. Result := SizeOf(LongWord);
  1502. otSQWord,
  1503. otUQWord:
  1504. Result := SizeOf(QWord);
  1505. end;
  1506. tkChar:
  1507. Result := SizeOf(AnsiChar);
  1508. tkFloat:
  1509. case TypeData^.FloatType of
  1510. ftSingle:
  1511. Result := SizeOf(Single);
  1512. ftDouble:
  1513. Result := SizeOf(Double);
  1514. ftExtended:
  1515. Result := SizeOf(Extended);
  1516. ftComp:
  1517. Result := SizeOf(Comp);
  1518. ftCurr:
  1519. Result := SizeOf(Currency);
  1520. end;
  1521. tkSet:
  1522. Result := TypeData^.SetSize;
  1523. tkMethod:
  1524. Result := SizeOf(TMethod);
  1525. tkSString:
  1526. { ShortString can hold max. 254 characters as [0] is Length and [255] is #0 }
  1527. Result := SizeOf(ShortString) - 2;
  1528. tkVariant:
  1529. Result := SizeOf(Variant);
  1530. tkProcVar:
  1531. Result := SizeOf(CodePointer);
  1532. tkWChar:
  1533. Result := SizeOf(WideChar);
  1534. tkUChar:
  1535. Result := SizeOf(UnicodeChar);
  1536. tkFile:
  1537. { ToDo }
  1538. Result := SizeOf(TTextRec);
  1539. tkAString,
  1540. tkWString,
  1541. tkUString,
  1542. tkInterface,
  1543. tkDynArray,
  1544. tkClass,
  1545. tkHelper,
  1546. tkClassRef,
  1547. tkInterfaceRaw,
  1548. tkPointer:
  1549. Result := SizeOf(Pointer);
  1550. tkObject,
  1551. tkRecord:
  1552. Result := TypeData^.RecSize;
  1553. tkArray:
  1554. Result := TypeData^.ArrayData.Size;
  1555. tkUnknown,
  1556. tkLString:
  1557. Assert(False);
  1558. end;
  1559. end;
  1560. end;
  1561. class procedure TValue.Make(ABuffer: pointer; ATypeInfo: PTypeInfo; out result: TValue);
  1562. type
  1563. PMethod = ^TMethod;
  1564. var
  1565. td: PTypeData;
  1566. begin
  1567. result.Init;
  1568. result.FData.FTypeInfo:=ATypeInfo;
  1569. if not Assigned(ATypeInfo) then
  1570. Exit;
  1571. { first handle those types that need a TValueData implementation }
  1572. case ATypeInfo^.Kind of
  1573. tkSString : begin
  1574. td := GetTypeData(ATypeInfo);
  1575. result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, td^.MaxLength + 1, ATypeInfo, True);
  1576. end;
  1577. tkWString,
  1578. tkUString,
  1579. tkAString : result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  1580. tkDynArray : result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  1581. tkArray : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, Result.TypeData^.ArrayData.Size, ATypeInfo, False);
  1582. tkObject,
  1583. tkRecord : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, Result.TypeData^.RecSize, ATypeInfo, False);
  1584. tkVariant : result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, SizeOf(Variant), ATypeInfo, False);
  1585. tkInterface: result.FData.FValueData := TValueDataIntImpl.CreateRef(ABuffer, ATypeInfo, True);
  1586. end;
  1587. if not Assigned(ABuffer) then
  1588. Exit;
  1589. { now handle those that are happy with the variant part of FData }
  1590. case ATypeInfo^.Kind of
  1591. tkSString,
  1592. tkWString,
  1593. tkUString,
  1594. tkAString,
  1595. tkDynArray,
  1596. tkArray,
  1597. tkObject,
  1598. tkRecord,
  1599. tkVariant,
  1600. tkInterface:
  1601. { ignore }
  1602. ;
  1603. tkClass : result.FData.FAsObject := PPointer(ABuffer)^;
  1604. tkClassRef : result.FData.FAsClass := PClass(ABuffer)^;
  1605. tkInterfaceRaw : result.FData.FAsPointer := PPointer(ABuffer)^;
  1606. tkInt64 : result.FData.FAsSInt64 := PInt64(ABuffer)^;
  1607. tkQWord : result.FData.FAsUInt64 := PQWord(ABuffer)^;
  1608. tkProcVar : result.FData.FAsMethod.Code := PCodePointer(ABuffer)^;
  1609. tkMethod : result.FData.FAsMethod := PMethod(ABuffer)^;
  1610. tkPointer : result.FData.FAsPointer := PPointer(ABuffer)^;
  1611. tkSet : begin
  1612. td := GetTypeData(ATypeInfo);
  1613. case td^.OrdType of
  1614. otUByte: begin
  1615. { this can either really be 1 Byte or a set > 32-bit, so
  1616. check the underlying type }
  1617. if not (td^.CompType^.Kind in [tkInteger,tkEnumeration]) then
  1618. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  1619. case td^.SetSize of
  1620. 0, 1:
  1621. Result.FData.FAsUByte := PByte(ABuffer)^;
  1622. { these two cases shouldn't happen, but better safe than sorry... }
  1623. 2:
  1624. Result.FData.FAsUWord := PWord(ABuffer)^;
  1625. 3, 4:
  1626. Result.FData.FAsULong := PLongWord(ABuffer)^;
  1627. { maybe we should also allow storage as otUQWord? }
  1628. 5..8:
  1629. Result.FData.FAsUInt64 := PQWord(ABuffer)^;
  1630. else
  1631. Result.FData.FValueData := TValueDataIntImpl.CreateCopy(ABuffer, td^.SetSize, ATypeInfo, False);
  1632. end;
  1633. end;
  1634. otUWord:
  1635. Result.FData.FAsUWord := PWord(ABuffer)^;
  1636. otULong:
  1637. Result.FData.FAsULong := PLongWord(ABuffer)^;
  1638. else
  1639. { ehm... Panic? }
  1640. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  1641. end;
  1642. end;
  1643. tkChar,
  1644. tkWChar,
  1645. tkUChar,
  1646. tkEnumeration,
  1647. tkInteger : begin
  1648. case GetTypeData(ATypeInfo)^.OrdType of
  1649. otSByte: result.FData.FAsSByte := PShortInt(ABuffer)^;
  1650. otUByte: result.FData.FAsUByte := PByte(ABuffer)^;
  1651. otSWord: result.FData.FAsSWord := PSmallInt(ABuffer)^;
  1652. otUWord: result.FData.FAsUWord := PWord(ABuffer)^;
  1653. otSLong: result.FData.FAsSLong := PLongInt(ABuffer)^;
  1654. otULong: result.FData.FAsULong := PLongWord(ABuffer)^;
  1655. end;
  1656. end;
  1657. tkBool : begin
  1658. case GetTypeData(ATypeInfo)^.OrdType of
  1659. otUByte: result.FData.FAsUByte := Byte(System.PBoolean(ABuffer)^);
  1660. otUWord: result.FData.FAsUWord := Word(PBoolean16(ABuffer)^);
  1661. otULong: result.FData.FAsULong := DWord(PBoolean32(ABuffer)^);
  1662. otUQWord: result.FData.FAsUInt64 := QWord(PBoolean64(ABuffer)^);
  1663. otSByte: result.FData.FAsSByte := ShortInt(PByteBool(ABuffer)^);
  1664. otSWord: result.FData.FAsSWord := SmallInt(PWordBool(ABuffer)^);
  1665. otSLong: result.FData.FAsSLong := LongInt(PLongBool(ABuffer)^);
  1666. otSQWord: result.FData.FAsSInt64 := Int64(PQWordBool(ABuffer)^);
  1667. end;
  1668. end;
  1669. tkFloat : begin
  1670. case GetTypeData(ATypeInfo)^.FloatType of
  1671. ftCurr : result.FData.FAsCurr := PCurrency(ABuffer)^;
  1672. ftSingle : result.FData.FAsSingle := PSingle(ABuffer)^;
  1673. ftDouble : result.FData.FAsDouble := PDouble(ABuffer)^;
  1674. ftExtended: result.FData.FAsExtended := PExtended(ABuffer)^;
  1675. ftComp : result.FData.FAsComp := PComp(ABuffer)^;
  1676. end;
  1677. end;
  1678. else
  1679. raise Exception.CreateFmt(SErrUnableToGetValueForType,[ATypeInfo^.Name]);
  1680. end;
  1681. end;
  1682. class procedure TValue.Make(AValue: NativeInt; ATypeInfo: PTypeInfo; out Result: TValue);
  1683. begin
  1684. TValue.Make(@AValue, ATypeInfo, Result);
  1685. end;
  1686. class procedure TValue.MakeOpenArray(AArray: Pointer; ALength: SizeInt; ATypeInfo: PTypeInfo; out Result: TValue);
  1687. var
  1688. el: TValue;
  1689. begin
  1690. Result.FData.FTypeInfo := ATypeInfo;
  1691. { resets the whole variant part; FValueData is already Nil }
  1692. {$if SizeOf(TMethod) > SizeOf(QWord)}
  1693. Result.FData.FAsMethod.Code := Nil;
  1694. Result.FData.FAsMethod.Data := Nil;
  1695. {$else}
  1696. Result.FData.FAsUInt64 := 0;
  1697. {$endif}
  1698. if not Assigned(ATypeInfo) then
  1699. Exit;
  1700. if ATypeInfo^.Kind <> tkArray then
  1701. Exit;
  1702. if not Assigned(AArray) then
  1703. Exit;
  1704. if ALength < 0 then
  1705. Exit;
  1706. Result.FData.FValueData := TValueDataIntImpl.CreateRef(@AArray, ATypeInfo, False);
  1707. Result.FData.FArrLength := ALength;
  1708. Make(Nil, Result.TypeData^.ArrayData.ElType, el);
  1709. Result.FData.FElSize := el.DataSize;
  1710. end;
  1711. {$ifndef NoGenericMethods}
  1712. generic class procedure TValue.Make<T>(const AValue: T; out Result: TValue);
  1713. begin
  1714. TValue.Make(@AValue, PTypeInfo(System.TypeInfo(T)), Result);
  1715. end;
  1716. generic class function TValue.From<T>(constref aValue: T): TValue;
  1717. begin
  1718. TValue.Make(@aValue, PTypeInfo(System.TypeInfo(T)), Result);
  1719. end;
  1720. generic class function TValue.FromOpenArray<T>(constref aValue: array of T): TValue;
  1721. var
  1722. arrdata: Pointer;
  1723. begin
  1724. if Length(aValue) > 0 then
  1725. arrdata := @aValue[0]
  1726. else
  1727. arrdata := Nil;
  1728. TValue.MakeOpenArray(arrdata, Length(aValue), PTypeInfo(System.TypeInfo(aValue)), Result);
  1729. end;
  1730. {$endif}
  1731. class function TValue.FromOrdinal(aTypeInfo: PTypeInfo; aValue: Int64): TValue;
  1732. {$ifdef ENDIAN_BIG}
  1733. var
  1734. p: PByte;
  1735. td: PTypeData;
  1736. {$endif}
  1737. begin
  1738. if not Assigned(aTypeInfo) or
  1739. not (aTypeInfo^.Kind in [tkInteger, tkInt64, tkQWord, tkEnumeration, tkBool, tkChar, tkWChar, tkUChar]) then
  1740. raise EInvalidCast.Create(SErrInvalidTypecast);
  1741. {$ifdef ENDIAN_BIG}
  1742. td := GetTypeData(aTypeInfo);
  1743. p := @aValue;
  1744. case td^.OrdType of
  1745. otSByte,
  1746. otUByte:
  1747. p := p + 7;
  1748. otSWord,
  1749. otUWord:
  1750. p := p + 6;
  1751. otSLong,
  1752. otULong:
  1753. p := p + 4;
  1754. otSQWord,
  1755. otUQWord: ;
  1756. end;
  1757. TValue.Make(p, aTypeInfo, Result);
  1758. {$else}
  1759. TValue.Make(@aValue, aTypeInfo, Result);
  1760. {$endif}
  1761. end;
  1762. class function TValue.FromArray(aArrayTypeInfo: PTypeInfo; const aValues: array of TValue): TValue; static;
  1763. var
  1764. i, sz: SizeInt;
  1765. data: TValueDataIntImpl;
  1766. begin
  1767. Result.Init;
  1768. Result.FData.FTypeInfo := aArrayTypeInfo;
  1769. if not Assigned(aArrayTypeInfo) then
  1770. Exit;
  1771. if aArrayTypeInfo^.Kind = tkDynArray then begin
  1772. data := TValueDataIntImpl.CreateRef(Nil, aArrayTypeInfo, True);
  1773. sz := Length(aValues);
  1774. DynArraySetLength(data.FBuffer, aArrayTypeInfo, 1, @sz);
  1775. Result.FData.FValueData := data;
  1776. end else if aArrayTypeInfo^.Kind = tkArray then begin
  1777. if Result.GetArrayLength <> Length(aValues) then
  1778. raise ERtti.CreateFmt(SErrLengthOfArrayMismatch, [Length(aValues), Result.GetArrayLength]);
  1779. Result.FData.FValueData := TValueDataIntImpl.CreateCopy(Nil, Result.TypeData^.ArrayData.Size, aArrayTypeInfo, False);
  1780. end else
  1781. raise ERtti.CreateFmt(SErrTypeKindNotSupported, [aArrayTypeInfo^.Name]);
  1782. for i := 0 to High(aValues) do
  1783. Result.SetArrayElement(i, aValues[i]);
  1784. end;
  1785. class function TValue.FromVarRec(const aValue: TVarRec): TValue;
  1786. begin
  1787. Result:=Default(TValue);
  1788. case aValue.VType of
  1789. vtInteger: Result:=aValue.VInteger;
  1790. vtBoolean: Result:=aValue.VBoolean;
  1791. vtWideChar: TValue.Make(@aValue.VWideChar,System.TypeInfo(WideChar),Result);
  1792. vtInt64: Result:=aValue.VInt64^;
  1793. vtQWord: Result:=aValue.VQWord^;
  1794. vtChar: TValue.Make(@aValue.VChar,System.TypeInfo(AnsiChar),Result);
  1795. vtPChar: Result:=string(aValue.VPChar);
  1796. vtPWideChar: Result:=widestring(aValue.VPWideChar);
  1797. vtString: Result:=aValue.VString^;
  1798. vtWideString: Result:=WideString(aValue.VWideString);
  1799. vtAnsiString: Result:=AnsiString(aValue.VAnsiString);
  1800. vtUnicodeString: Result:=UnicodeString(aValue.VUnicodeString);
  1801. vtObject: Result:=TObject(aValue.VObject);
  1802. vtPointer: TValue.Make(@aValue.VPointer,System.TypeInfo(Pointer),Result);
  1803. vtInterface: Result:=IInterface(aValue.VInterface);
  1804. vtClass: Result:=aValue.VClass;
  1805. vtVariant: TValue.Make(@aValue.VVariant^,System.TypeInfo(Variant),result);
  1806. vtExtended: Result := aValue.VExtended^;
  1807. vtCurrency: Result := aValue.VCurrency^;
  1808. end;
  1809. end;
  1810. class function TValue.FromVariant(const aValue : Variant) : TValue;
  1811. var
  1812. aType : TVarType;
  1813. begin
  1814. Result:=Default(TValue);
  1815. aType:=TVarData(aValue).vtype;
  1816. case aType of
  1817. varEmpty,
  1818. VarNull : TValue.Make(@aValue,System.TypeInfo(Variant),Result);
  1819. varInteger : Result:=Integer(aValue);
  1820. varSmallInt : Result:=SmallInt(aValue);
  1821. varBoolean : Result:=Boolean(aValue);
  1822. varOleStr: Result:=WideString(aValue);
  1823. varInt64: Result:=Int64(aValue);
  1824. varQWord: Result:=QWord(aValue);
  1825. varShortInt: Result:=ShortInt(aValue);
  1826. varByte : Result:=Byte(aValue);
  1827. varWord : Result:=Word(aValue);
  1828. varLongWord : Result:=Cardinal(aValue);
  1829. varSingle : Result:=Single(aValue);
  1830. varDouble : Result:=Double(aValue);
  1831. varDate : TValue.Make(@TVarData(aValue).vDate,System.TypeInfo(TDateTime),Result);
  1832. varDispatch : TValue.Make(@TVarData(aValue).VDispatch,System.TypeInfo(IDispatch),Result);
  1833. varError : TValue.Make(@TVarData(aValue).vDate,System.TypeInfo(HRESULT),Result);
  1834. varUnknown : TValue.Make(@TVarData(aValue).vunknown,System.TypeInfo(IUnknown),Result);
  1835. varCurrency : Result:=Currency(aValue);
  1836. varString : Result:=AnsiString(aValue);
  1837. varUString : Result:=UnicodeString(TVarData(aValue).vustring);
  1838. else
  1839. raise EVariantTypeCastError.CreateFmt('Invalid variant cast from type %d',[aType]);
  1840. end;
  1841. end;
  1842. function TValue.GetIsEmpty: boolean;
  1843. begin
  1844. result := (FData.FTypeInfo=nil) or
  1845. ((Kind in [tkSString, tkObject, tkRecord, tkArray]) and not Assigned(FData.FValueData)) or
  1846. ((Kind in [tkClass, tkClassRef, tkInterfaceRaw]) and not Assigned(FData.FAsPointer));
  1847. end;
  1848. function TValue.IsArray: boolean;
  1849. begin
  1850. result := kind in [tkArray, tkDynArray];
  1851. end;
  1852. function TValue.IsOpenArray: Boolean;
  1853. var
  1854. td: PTypeData;
  1855. begin
  1856. td := TypeData;
  1857. Result := (Kind = tkArray) and (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0)
  1858. end;
  1859. function TValue.AsString: string;
  1860. begin
  1861. if System.GetTypeKind(String) = tkUString then
  1862. Result := String(AsUnicodeString)
  1863. else
  1864. Result := String(AsAnsiString);
  1865. end;
  1866. function TValue.AsUnicodeString: UnicodeString;
  1867. begin
  1868. if (Kind in [tkSString, tkAString, tkUString, tkWString]) and not Assigned(FData.FValueData) then
  1869. Result := ''
  1870. else
  1871. case Kind of
  1872. tkSString:
  1873. Result := UnicodeString(PShortString(FData.FValueData.GetReferenceToRawData)^);
  1874. tkAString:
  1875. Result := UnicodeString(PAnsiString(FData.FValueData.GetReferenceToRawData)^);
  1876. tkWString:
  1877. Result := UnicodeString(PWideString(FData.FValueData.GetReferenceToRawData)^);
  1878. tkUString:
  1879. Result := UnicodeString(PUnicodeString(FData.FValueData.GetReferenceToRawData)^);
  1880. else
  1881. raise EInvalidCast.Create(SErrInvalidTypecast);
  1882. end;
  1883. end;
  1884. function TValue.AsAnsiString: AnsiString;
  1885. begin
  1886. if (Kind in [tkSString, tkAString, tkUString, tkWString]) and not Assigned(FData.FValueData) then
  1887. Result := ''
  1888. else
  1889. case Kind of
  1890. tkSString:
  1891. Result := AnsiString(PShortString(FData.FValueData.GetReferenceToRawData)^);
  1892. tkAString:
  1893. Result := AnsiString(PAnsiString(FData.FValueData.GetReferenceToRawData)^);
  1894. tkWString:
  1895. Result := AnsiString(PWideString(FData.FValueData.GetReferenceToRawData)^);
  1896. tkUString:
  1897. Result := AnsiString(PUnicodeString(FData.FValueData.GetReferenceToRawData)^);
  1898. else
  1899. raise EInvalidCast.Create(SErrInvalidTypecast);
  1900. end;
  1901. end;
  1902. function TValue.AsExtended: Extended;
  1903. begin
  1904. if Kind = tkFloat then
  1905. begin
  1906. case TypeData^.FloatType of
  1907. ftSingle : result := FData.FAsSingle;
  1908. ftDouble : result := FData.FAsDouble;
  1909. ftExtended : result := FData.FAsExtended;
  1910. ftCurr : result := FData.FAsCurr;
  1911. ftComp : result := FData.FAsComp;
  1912. else
  1913. raise EInvalidCast.Create(SErrInvalidTypecast);
  1914. end;
  1915. end
  1916. else if Kind in [tkInteger, tkInt64, tkQWord] then
  1917. Result := AsInt64
  1918. else
  1919. raise EInvalidCast.Create(SErrInvalidTypecast);
  1920. end;
  1921. function TValue.IsObject: boolean;
  1922. begin
  1923. result := (Kind = tkClass) or ((Kind = tkUnknown) and not Assigned(FData.FAsObject));
  1924. end;
  1925. function TValue.IsClass: boolean;
  1926. begin
  1927. result := (Kind = tkClassRef) or ((Kind in [tkClass,tkUnknown]) and not Assigned(FData.FAsObject));
  1928. end;
  1929. function TValue.IsOrdinal: boolean;
  1930. begin
  1931. result := (Kind in [tkInteger, tkInt64, tkQWord, tkBool, tkEnumeration, tkChar, tkWChar, tkUChar]) or
  1932. ((Kind in [tkClass, tkClassRef, tkInterfaceRaw, tkUnknown]) and not Assigned(FData.FAsPointer));
  1933. end;
  1934. function TValue.IsType(ATypeInfo: PTypeInfo): boolean;
  1935. begin
  1936. result := ATypeInfo = TypeInfo;
  1937. end;
  1938. {$ifndef NoGenericMethods}
  1939. generic function TValue.IsType<T>:Boolean;
  1940. begin
  1941. Result := IsType(PTypeInfo(System.TypeInfo(T)));
  1942. end;
  1943. {$endif}
  1944. function TValue.AsObject: TObject;
  1945. begin
  1946. if IsObject or (IsClass and not Assigned(FData.FAsObject)) then
  1947. result := TObject(FData.FAsObject)
  1948. else
  1949. raise EInvalidCast.Create(SErrInvalidTypecast);
  1950. end;
  1951. function TValue.AsClass: TClass;
  1952. begin
  1953. if IsClass then
  1954. result := FData.FAsClass
  1955. else
  1956. raise EInvalidCast.Create(SErrInvalidTypecast);
  1957. end;
  1958. function TValue.AsBoolean: boolean;
  1959. begin
  1960. if (Kind = tkBool) then
  1961. case TypeData^.OrdType of
  1962. otSByte: Result := ByteBool(FData.FAsSByte);
  1963. otUByte: Result := Boolean(FData.FAsUByte);
  1964. otSWord: Result := WordBool(FData.FAsSWord);
  1965. otUWord: Result := Boolean16(FData.FAsUWord);
  1966. otSLong: Result := LongBool(FData.FAsSLong);
  1967. otULong: Result := Boolean32(FData.FAsULong);
  1968. otSQWord: Result := QWordBool(FData.FAsSInt64);
  1969. otUQWord: Result := Boolean64(FData.FAsUInt64);
  1970. end
  1971. else
  1972. raise EInvalidCast.Create(SErrInvalidTypecast);
  1973. end;
  1974. function TValue.AsOrdinal: Int64;
  1975. begin
  1976. if IsOrdinal then
  1977. if Kind in [tkClass, tkClassRef, tkInterfaceRaw, tkUnknown] then
  1978. Result := 0
  1979. else
  1980. case TypeData^.OrdType of
  1981. otSByte: Result := FData.FAsSByte;
  1982. otUByte: Result := FData.FAsUByte;
  1983. otSWord: Result := FData.FAsSWord;
  1984. otUWord: Result := FData.FAsUWord;
  1985. otSLong: Result := FData.FAsSLong;
  1986. otULong: Result := FData.FAsULong;
  1987. otSQWord: Result := FData.FAsSInt64;
  1988. otUQWord: Result := FData.FAsUInt64;
  1989. end
  1990. else
  1991. raise EInvalidCast.Create(SErrInvalidTypecast);
  1992. end;
  1993. function TValue.AsCurrency: Currency;
  1994. begin
  1995. if (Kind = tkFloat) and (TypeData^.FloatType=ftCurr) then
  1996. result := FData.FAsCurr
  1997. else
  1998. raise EInvalidCast.Create(SErrInvalidTypecast);
  1999. end;
  2000. function TValue.AsSingle: Single;
  2001. begin
  2002. if Kind = tkFloat then
  2003. begin
  2004. case TypeData^.FloatType of
  2005. ftSingle : result := FData.FAsSingle;
  2006. ftDouble : result := FData.FAsDouble;
  2007. ftExtended : result := FData.FAsExtended;
  2008. ftCurr : result := FData.FAsCurr;
  2009. ftComp : result := FData.FAsComp;
  2010. else
  2011. raise EInvalidCast.Create(SErrInvalidTypecast);
  2012. end;
  2013. end
  2014. else if Kind in [tkInteger, tkInt64, tkQWord] then
  2015. Result := AsInt64
  2016. else
  2017. raise EInvalidCast.Create(SErrInvalidTypecast);
  2018. end;
  2019. function TValue.AsDateTime: TDateTime;
  2020. begin
  2021. if (Kind = tkFloat) and (TypeData^.FloatType=ftDouble) and (TypeInfo=System.TypeInfo(TDateTime)) then
  2022. result := FData.FAsDouble
  2023. else
  2024. raise EInvalidCast.Create(SErrInvalidTypecast);
  2025. end;
  2026. function TValue.AsDouble: Double;
  2027. begin
  2028. if Kind = tkFloat then
  2029. begin
  2030. case TypeData^.FloatType of
  2031. ftSingle : result := FData.FAsSingle;
  2032. ftDouble : result := FData.FAsDouble;
  2033. ftExtended : result := FData.FAsExtended;
  2034. ftCurr : result := FData.FAsCurr;
  2035. ftComp : result := FData.FAsComp;
  2036. else
  2037. raise EInvalidCast.Create(SErrInvalidTypecast);
  2038. end;
  2039. end
  2040. else if Kind in [tkInteger, tkInt64, tkQWord] then
  2041. Result := AsInt64
  2042. else
  2043. raise EInvalidCast.Create(SErrInvalidTypecast);
  2044. end;
  2045. function TValue.AsError: HRESULT;
  2046. begin
  2047. if (Kind = tkInteger) and (TypeInfo=System.TypeInfo(HRESULT)) then
  2048. result := HResult(AsInteger)
  2049. else
  2050. raise EInvalidCast.Create(SErrInvalidTypecast);
  2051. end;
  2052. function TValue.AsInteger: Integer;
  2053. begin
  2054. if Kind in [tkInteger, tkInt64, tkQWord] then
  2055. case TypeData^.OrdType of
  2056. otSByte: Result := FData.FAsSByte;
  2057. otUByte: Result := FData.FAsUByte;
  2058. otSWord: Result := FData.FAsSWord;
  2059. otUWord: Result := FData.FAsUWord;
  2060. otSLong: Result := FData.FAsSLong;
  2061. otULong: Result := FData.FAsULong;
  2062. otSQWord: Result := FData.FAsSInt64;
  2063. otUQWord: Result := FData.FAsUInt64;
  2064. end
  2065. else
  2066. raise EInvalidCast.Create(SErrInvalidTypecast);
  2067. end;
  2068. function TValue.AsAnsiChar: AnsiChar;
  2069. begin
  2070. if Kind = tkChar then
  2071. Result := Chr(FData.FAsUByte)
  2072. else
  2073. raise EInvalidCast.Create(SErrInvalidTypecast);
  2074. end;
  2075. function TValue.AsWideChar: WideChar;
  2076. begin
  2077. if Kind = tkWChar then
  2078. Result := WideChar(FData.FAsUWord)
  2079. else
  2080. raise EInvalidCast.Create(SErrInvalidTypecast);
  2081. end;
  2082. function TValue.AsChar: AnsiChar;
  2083. begin
  2084. {$if SizeOf(AnsiChar) = 1}
  2085. Result := AsAnsiChar;
  2086. {$else}
  2087. Result := AsWideChar;
  2088. {$endif}
  2089. end;
  2090. function TValue.AsPointer : Pointer;
  2091. begin
  2092. if Kind in [tkPointer, tkInterface, tkInterfaceRaw, tkClass,tkClassRef,tkAString,tkWideString,tkUnicodeString] then
  2093. Result:=FData.FAsPointer
  2094. else
  2095. raise EInvalidCast.Create(SErrInvalidTypecast);
  2096. end;
  2097. function TValue.AsVariant : Variant;
  2098. begin
  2099. if (Kind=tkVariant) then
  2100. Result:= PVariant(FData.FValueData.GetReferenceToRawData)^
  2101. else
  2102. raise EInvalidCast.Create(SErrInvalidTypecast);
  2103. end;
  2104. function TValue.AsInt64: Int64;
  2105. begin
  2106. if Kind in [tkInteger, tkInt64, tkQWord] then
  2107. case TypeData^.OrdType of
  2108. otSByte: Result := FData.FAsSByte;
  2109. otUByte: Result := FData.FAsUByte;
  2110. otSWord: Result := FData.FAsSWord;
  2111. otUWord: Result := FData.FAsUWord;
  2112. otSLong: Result := FData.FAsSLong;
  2113. otULong: Result := FData.FAsULong;
  2114. otSQWord: Result := FData.FAsSInt64;
  2115. otUQWord: Result := FData.FAsUInt64;
  2116. end
  2117. else if (Kind = tkFloat) and (TypeData^.FloatType = ftComp) then
  2118. Result := Int64(FData.FAsComp)
  2119. else
  2120. raise EInvalidCast.Create(SErrInvalidTypecast);
  2121. end;
  2122. function TValue.AsUInt64: QWord;
  2123. begin
  2124. if Kind in [tkInteger, tkInt64, tkQWord] then
  2125. case TypeData^.OrdType of
  2126. otSByte: Result := FData.FAsSByte;
  2127. otUByte: Result := FData.FAsUByte;
  2128. otSWord: Result := FData.FAsSWord;
  2129. otUWord: Result := FData.FAsUWord;
  2130. otSLong: Result := FData.FAsSLong;
  2131. otULong: Result := FData.FAsULong;
  2132. otSQWord: Result := FData.FAsSInt64;
  2133. otUQWord: Result := FData.FAsUInt64;
  2134. end
  2135. else if (Kind = tkFloat) and (TypeData^.FloatType = ftComp) then
  2136. Result := QWord(FData.FAsComp)
  2137. else
  2138. raise EInvalidCast.Create(SErrInvalidTypecast);
  2139. end;
  2140. function TValue.AsInterface: IInterface;
  2141. begin
  2142. if Kind = tkInterface then
  2143. Result := PInterface(FData.FValueData.GetReferenceToRawData)^
  2144. else if (Kind in [tkClass, tkClassRef, tkUnknown]) and not Assigned(FData.FAsPointer) then
  2145. Result := Nil
  2146. else
  2147. raise EInvalidCast.Create(SErrInvalidTypecast);
  2148. end;
  2149. function TValue.ToString: String;
  2150. begin
  2151. case Kind of
  2152. tkWString,
  2153. tkUString : result := AsUnicodeString;
  2154. tkSString,
  2155. tkAString : result := AsAnsiString;
  2156. tkInteger : result := IntToStr(AsInteger);
  2157. tkQWord : result := IntToStr(AsUInt64);
  2158. tkInt64 : result := IntToStr(AsInt64);
  2159. tkBool : result := BoolToStr(AsBoolean, True);
  2160. tkPointer : result := '(pointer @ ' + HexStr(FData.FAsPointer) + ')';
  2161. tkInterface : result := '(interface @ ' + HexStr(PPointer(FData.FValueData.GetReferenceToRawData)^) + ')';
  2162. tkInterfaceRaw : result := '(raw interface @ ' + HexStr(FData.FAsPointer) + ')';
  2163. tkEnumeration: Result := GetEnumName(TypeInfo, Integer(AsOrdinal));
  2164. tkChar: Result := AnsiChar(FData.FAsUByte);
  2165. tkWChar: Result := UTF8Encode(WideChar(FData.FAsUWord));
  2166. else
  2167. result := '';
  2168. end;
  2169. end;
  2170. function TValue.GetArrayLength: SizeInt;
  2171. var
  2172. td: PTypeData;
  2173. begin
  2174. if not IsArray then
  2175. raise EInvalidCast.Create(SErrInvalidTypecast);
  2176. if Kind = tkDynArray then
  2177. Result := DynArraySize(PPointer(FData.FValueData.GetReferenceToRawData)^)
  2178. else begin
  2179. td := TypeData;
  2180. if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then
  2181. Result := FData.FArrLength
  2182. else
  2183. Result := td^.ArrayData.ElCount;
  2184. end;
  2185. end;
  2186. function TValue.GetArrayElement(AIndex: SizeInt): TValue;
  2187. var
  2188. data: Pointer;
  2189. eltype: PTypeInfo;
  2190. elsize: SizeInt;
  2191. td: PTypeData;
  2192. begin
  2193. if not IsArray then
  2194. raise EInvalidCast.Create(SErrInvalidTypecast);
  2195. if Kind = tkDynArray then begin
  2196. data := DynArrayIndex(PPointer(FData.FValueData.GetReferenceToRawData)^, [AIndex], FData.FTypeInfo);
  2197. eltype := TypeData^.elType2;
  2198. end else begin
  2199. td := TypeData;
  2200. eltype := td^.ArrayData.ElType;
  2201. { open array? }
  2202. if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then begin
  2203. data := PPointer(FData.FValueData.GetReferenceToRawData)^;
  2204. elsize := FData.FElSize
  2205. end else begin
  2206. data := FData.FValueData.GetReferenceToRawData;
  2207. elsize := td^.ArrayData.Size div td^.ArrayData.ElCount;
  2208. end;
  2209. data := PByte(data) + AIndex * elsize;
  2210. end;
  2211. { MakeWithoutCopy? }
  2212. Make(data, eltype, Result);
  2213. end;
  2214. procedure TValue.SetArrayElement(AIndex: SizeInt; constref AValue: TValue);
  2215. var
  2216. data: Pointer;
  2217. eltype: PTypeInfo;
  2218. elsize: SizeInt;
  2219. td, tdv: PTypeData;
  2220. begin
  2221. if not IsArray then
  2222. raise EInvalidCast.Create(SErrInvalidTypecast);
  2223. if Kind = tkDynArray then begin
  2224. data := DynArrayIndex(PPointer(FData.FValueData.GetReferenceToRawData)^, [AIndex], FData.FTypeInfo);
  2225. eltype := TypeData^.elType2;
  2226. end else begin
  2227. td := TypeData;
  2228. eltype := td^.ArrayData.ElType;
  2229. { open array? }
  2230. if (td^.ArrayData.Size = 0) and (td^.ArrayData.ElCount = 0) then begin
  2231. data := PPointer(FData.FValueData.GetReferenceToRawData)^;
  2232. elsize := FData.FElSize
  2233. end else begin
  2234. data := FData.FValueData.GetReferenceToRawData;
  2235. elsize := td^.ArrayData.Size div td^.ArrayData.ElCount;
  2236. end;
  2237. data := PByte(data) + AIndex * elsize;
  2238. end;
  2239. { maybe we'll later on allow some typecasts, but for now be restrictive }
  2240. if eltype^.Kind <> AValue.Kind then
  2241. raise EInvalidCast.Create(SErrInvalidTypecast);
  2242. td := GetTypeData(eltype);
  2243. tdv := AValue.TypeData;
  2244. if ((eltype^.Kind in [tkInteger, tkBool, tkEnumeration, tkSet]) and (td^.OrdType <> tdv^.OrdType)) or
  2245. ((eltype^.Kind = tkFloat) and (td^.FloatType <> tdv^.FloatType)) then
  2246. raise EInvalidCast.Create(SErrInvalidTypecast);
  2247. if Assigned(AValue.FData.FValueData) and (eltype^.Kind <> tkSString) then
  2248. IntCopy(AValue.FData.FValueData.GetReferenceToRawData, data, eltype)
  2249. else
  2250. Move(AValue.GetReferenceToRawData^, data^, AValue.DataSize);
  2251. end;
  2252. function TValue.TryAsOrdinal(out AResult: int64): boolean;
  2253. begin
  2254. result := IsOrdinal;
  2255. if result then
  2256. AResult := AsOrdinal;
  2257. end;
  2258. function TValue.GetReferenceToRawData: Pointer;
  2259. begin
  2260. if not Assigned(FData.FTypeInfo) then
  2261. Result := Nil
  2262. else if Assigned(FData.FValueData) then
  2263. Result := FData.FValueData.GetReferenceToRawData
  2264. else begin
  2265. Result := Nil;
  2266. case Kind of
  2267. tkInteger,
  2268. tkEnumeration,
  2269. tkInt64,
  2270. tkQWord,
  2271. tkBool:
  2272. case TypeData^.OrdType of
  2273. otSByte:
  2274. Result := @FData.FAsSByte;
  2275. otUByte:
  2276. Result := @FData.FAsUByte;
  2277. otSWord:
  2278. Result := @FData.FAsSWord;
  2279. otUWord:
  2280. Result := @FData.FAsUWord;
  2281. otSLong:
  2282. Result := @FData.FAsSLong;
  2283. otULong:
  2284. Result := @FData.FAsULong;
  2285. otSQWord:
  2286. Result := @FData.FAsSInt64;
  2287. otUQWord:
  2288. Result := @FData.FAsUInt64;
  2289. end;
  2290. tkSet: begin
  2291. case TypeData^.OrdType of
  2292. otUByte: begin
  2293. case TypeData^.SetSize of
  2294. 1:
  2295. Result := @FData.FAsUByte;
  2296. 2:
  2297. Result := @FData.FAsUWord;
  2298. 3, 4:
  2299. Result := @FData.FAsULong;
  2300. 5..8:
  2301. Result := @FData.FAsUInt64;
  2302. else
  2303. { this should have gone through FAsValueData :/ }
  2304. Result := Nil;
  2305. end;
  2306. end;
  2307. otUWord:
  2308. Result := @FData.FAsUWord;
  2309. otULong:
  2310. Result := @FData.FAsULong;
  2311. else
  2312. Result := Nil;
  2313. end;
  2314. end;
  2315. tkChar:
  2316. Result := @FData.FAsUByte;
  2317. tkFloat:
  2318. case TypeData^.FloatType of
  2319. ftSingle:
  2320. Result := @FData.FAsSingle;
  2321. ftDouble:
  2322. Result := @FData.FAsDouble;
  2323. ftExtended:
  2324. Result := @FData.FAsExtended;
  2325. ftComp:
  2326. Result := @FData.FAsComp;
  2327. ftCurr:
  2328. Result := @FData.FAsCurr;
  2329. end;
  2330. tkMethod:
  2331. Result := @FData.FAsMethod;
  2332. tkClass:
  2333. Result := @FData.FAsObject;
  2334. tkWChar:
  2335. Result := @FData.FAsUWord;
  2336. tkInterfaceRaw:
  2337. Result := @FData.FAsPointer;
  2338. tkProcVar:
  2339. Result := @FData.FAsMethod.Code;
  2340. tkUChar:
  2341. Result := @FData.FAsUWord;
  2342. tkFile:
  2343. Result := @FData.FAsPointer;
  2344. tkClassRef:
  2345. Result := @FData.FAsClass;
  2346. tkPointer:
  2347. Result := @FData.FAsPointer;
  2348. tkVariant,
  2349. tkDynArray,
  2350. tkArray,
  2351. tkObject,
  2352. tkRecord,
  2353. tkInterface,
  2354. tkSString,
  2355. tkLString,
  2356. tkAString,
  2357. tkUString,
  2358. tkWString:
  2359. Assert(false, 'Managed/complex type not handled through IValueData');
  2360. end;
  2361. end;
  2362. end;
  2363. procedure TValue.ExtractRawData(ABuffer: Pointer);
  2364. begin
  2365. if Assigned(FData.FValueData) then
  2366. FData.FValueData.ExtractRawData(ABuffer)
  2367. else if Assigned(FData.FTypeInfo) then
  2368. Move((@FData.FAsPointer)^, ABuffer^, DataSize);
  2369. end;
  2370. procedure TValue.ExtractRawDataNoCopy(ABuffer: Pointer);
  2371. begin
  2372. if Assigned(FData.FValueData) then
  2373. FData.FValueData.ExtractRawDataNoCopy(ABuffer)
  2374. else if Assigned(FData.FTypeInfo) then
  2375. Move((@FData.FAsPointer)^, ABuffer^, DataSize);
  2376. end;
  2377. class operator TValue.:=(const AValue: ShortString): TValue;
  2378. begin
  2379. Make(@AValue, System.TypeInfo(AValue), Result);
  2380. end;
  2381. class operator TValue.:=(const AValue: AnsiString): TValue;
  2382. begin
  2383. Make(@AValue, System.TypeInfo(AValue), Result);
  2384. end;
  2385. class operator TValue.:=(const AValue: UnicodeString): TValue;
  2386. begin
  2387. Make(@AValue, System.TypeInfo(AValue), Result);
  2388. end;
  2389. class operator TValue.:=(const AValue: WideString): TValue;
  2390. begin
  2391. Make(@AValue, System.TypeInfo(AValue), Result);
  2392. end;
  2393. class operator TValue.:= (AValue: SmallInt): TValue;
  2394. begin
  2395. Make(@AValue, System.TypeInfo(AValue), Result);
  2396. end;
  2397. class operator TValue.:= (AValue: ShortInt): TValue;
  2398. begin
  2399. Make(@AValue, System.TypeInfo(AValue), Result);
  2400. end;
  2401. class operator TValue.:= (AValue: Byte): TValue; inline;
  2402. begin
  2403. Make(@AValue, System.TypeInfo(AValue), Result);
  2404. end;
  2405. class operator TValue.:= (AValue: Word): TValue; inline;
  2406. begin
  2407. Make(@AValue, System.TypeInfo(AValue), Result);
  2408. end;
  2409. class operator TValue.:= (AValue: Cardinal): TValue; inline;
  2410. begin
  2411. Make(@AValue, System.TypeInfo(AValue), Result);
  2412. end;
  2413. class operator TValue.:=(AValue: LongInt): TValue;
  2414. begin
  2415. Make(@AValue, System.TypeInfo(AValue), Result);
  2416. end;
  2417. class operator TValue.:=(AValue: Single): TValue;
  2418. begin
  2419. Make(@AValue, System.TypeInfo(AValue), Result);
  2420. end;
  2421. class operator TValue.:=(AValue: Double): TValue;
  2422. begin
  2423. Make(@AValue, System.TypeInfo(AValue), Result);
  2424. end;
  2425. {$ifdef FPC_HAS_TYPE_EXTENDED}
  2426. class operator TValue.:=(AValue: Extended): TValue;
  2427. begin
  2428. Make(@AValue, System.TypeInfo(AValue), Result);
  2429. end;
  2430. {$endif}
  2431. class operator TValue.:=(AValue: Currency): TValue;
  2432. begin
  2433. Make(@AValue, System.TypeInfo(AValue), Result);
  2434. end;
  2435. class operator TValue.:=(AValue: Comp): TValue;
  2436. begin
  2437. Make(@AValue, System.TypeInfo(AValue), Result);
  2438. end;
  2439. class operator TValue.:=(AValue: Int64): TValue;
  2440. begin
  2441. Make(@AValue, System.TypeInfo(AValue), Result);
  2442. end;
  2443. class operator TValue.:=(AValue: QWord): TValue;
  2444. begin
  2445. Make(@AValue, System.TypeInfo(AValue), Result);
  2446. end;
  2447. class operator TValue.:=(AValue: TObject): TValue;
  2448. begin
  2449. Make(@AValue, PTypeInfo(AValue.ClassInfo), Result);
  2450. end;
  2451. class operator TValue.:=(AValue: TClass): TValue;
  2452. begin
  2453. Make(@AValue, System.TypeInfo(AValue), Result);
  2454. end;
  2455. class operator TValue.:=(AValue: Boolean): TValue;
  2456. begin
  2457. Make(@AValue, System.TypeInfo(AValue), Result);
  2458. end;
  2459. class operator TValue.:=(AValue: IUnknown): TValue;
  2460. begin
  2461. Make(@AValue, System.TypeInfo(AValue), Result);
  2462. end;
  2463. class operator TValue.:= (AValue: TVarRec): TValue;
  2464. begin
  2465. Result:=TValue.FromVarRec(aValue);
  2466. end;
  2467. function Invoke(aCodeAddress: CodePointer; const aArgs: TValueArray;
  2468. aCallConv: TCallConv; aResultType: PTypeInfo; aIsStatic: Boolean;
  2469. aIsConstructor: Boolean): TValue;
  2470. var
  2471. funcargs: TFunctionCallParameterArray;
  2472. i: LongInt;
  2473. flags: TFunctionCallFlags;
  2474. begin
  2475. { sanity check }
  2476. if not Assigned(FuncCallMgr[aCallConv].Invoke) then
  2477. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  2478. { ToDo: handle IsConstructor }
  2479. if aIsConstructor then
  2480. raise ENotImplemented.Create(SErrInvokeNotImplemented);
  2481. flags := [];
  2482. if aIsStatic then
  2483. Include(flags, fcfStatic)
  2484. else if Length(aArgs) = 0 then
  2485. raise EInvocationError.Create(SErrMissingSelfParam);
  2486. SetLength(funcargs, Length(aArgs));
  2487. for i := Low(aArgs) to High(aArgs) do begin
  2488. funcargs[i - Low(aArgs) + Low(funcargs)].ValueRef := aArgs[i].GetReferenceToRawData;
  2489. funcargs[i - Low(aArgs) + Low(funcargs)].ValueSize := aArgs[i].DataSize;
  2490. funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParamType := aArgs[i].TypeInfo;
  2491. funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParamFlags := [];
  2492. funcargs[i - Low(aArgs) + Low(funcargs)].Info.ParaLocs := Nil;
  2493. end;
  2494. if Assigned(aResultType) then
  2495. TValue.Make(Nil, aResultType, Result)
  2496. else
  2497. Result := TValue.Empty;
  2498. FuncCallMgr[aCallConv].Invoke(aCodeAddress, funcargs, aCallConv, aResultType, Result.GetReferenceToRawData, flags);
  2499. end;
  2500. function Invoke(const aName: String; aCodeAddress: CodePointer; aCallConv: TCallConv; aStatic: Boolean; aInstance: TValue; constref aArgs: array of TValue; const aParams: TRttiParameterArray; aReturnType: TRttiType): TValue;
  2501. var
  2502. param: TRttiParameter;
  2503. unhidden, highs, i: SizeInt;
  2504. args: TFunctionCallParameterArray;
  2505. highargs: array of SizeInt;
  2506. restype: PTypeInfo;
  2507. resptr: Pointer;
  2508. mgr: TFunctionCallManager;
  2509. flags: TFunctionCallFlags;
  2510. begin
  2511. mgr := FuncCallMgr[aCallConv];
  2512. if not Assigned(mgr.Invoke) then
  2513. raise EInvocationError.CreateFmt(SErrCallConvNotSupported, [CCToStr(aCallConv)]);
  2514. if not Assigned(aCodeAddress) then
  2515. raise EInvocationError.CreateFmt(SErrInvokeNoCodeAddr, [aName]);
  2516. unhidden := 0;
  2517. highs := 0;
  2518. for param in aParams do begin
  2519. if unhidden < Length(aArgs) then begin
  2520. if pfArray in param.Flags then begin
  2521. if Assigned(aArgs[unhidden].TypeInfo) and not aArgs[unhidden].IsArray and (aArgs[unhidden].Kind <> param.ParamType.TypeKind) then
  2522. raise EInvocationError.CreateFmt(SErrInvokeArrayArgExpected, [param.Name, aName]);
  2523. end else if not (pfHidden in param.Flags) then begin
  2524. if Assigned(param.ParamType) and (aArgs[unhidden].Kind <> param.ParamType.TypeKind) then
  2525. raise EInvocationError.CreateFmt(SErrInvokeArgInvalidType, [param.Name, aName]);
  2526. end;
  2527. end;
  2528. if not (pfHidden in param.Flags) then
  2529. Inc(unhidden);
  2530. if pfHigh in param.Flags then
  2531. Inc(highs);
  2532. end;
  2533. if unhidden <> Length(aArgs) then
  2534. raise EInvocationError.CreateFmt(SErrInvokeArgCount, [aName, unhidden, Length(aArgs)]);
  2535. if Assigned(aReturnType) then begin
  2536. TValue.Make(Nil, aReturnType.FTypeInfo, Result);
  2537. resptr := Result.GetReferenceToRawData;
  2538. restype := aReturnType.FTypeInfo;
  2539. end else begin
  2540. Result := TValue.Empty;
  2541. resptr := Nil;
  2542. restype := Nil;
  2543. end;
  2544. SetLength(highargs, highs);
  2545. SetLength(args, Length(aParams));
  2546. unhidden := 0;
  2547. highs := 0;
  2548. for i := 0 to High(aParams) do begin
  2549. param := aParams[i];
  2550. if Assigned(param.ParamType) then
  2551. args[i].Info.ParamType := param.ParamType.FTypeInfo
  2552. else
  2553. args[i].Info.ParamType := Nil;
  2554. args[i].Info.ParamFlags := param.Flags;
  2555. args[i].Info.ParaLocs := Nil;
  2556. if pfHidden in param.Flags then begin
  2557. if pfSelf in param.Flags then
  2558. args[i].ValueRef := aInstance.GetReferenceToRawData
  2559. else if pfResult in param.Flags then begin
  2560. if not Assigned(restype) then
  2561. raise EInvocationError.CreateFmt(SErrInvokeRttiDataError, [aName]);
  2562. args[i].ValueRef := resptr;
  2563. restype := Nil;
  2564. resptr := Nil;
  2565. end else if pfHigh in param.Flags then begin
  2566. { the corresponding array argument is the *previous* unhidden argument }
  2567. if aArgs[unhidden - 1].IsArray then
  2568. highargs[highs] := aArgs[unhidden - 1].GetArrayLength - 1
  2569. else if not Assigned(aArgs[unhidden - 1].TypeInfo) then
  2570. highargs[highs] := -1
  2571. else
  2572. highargs[highs] := 0;
  2573. args[i].ValueRef := @highargs[highs];
  2574. Inc(highs);
  2575. end;
  2576. end else begin
  2577. if (pfArray in param.Flags) then begin
  2578. if not Assigned(aArgs[unhidden].TypeInfo) then
  2579. args[i].ValueRef := Nil
  2580. else if aArgs[unhidden].Kind = tkDynArray then
  2581. args[i].ValueRef := PPointer(aArgs[unhidden].GetReferenceToRawData)^
  2582. else
  2583. args[i].ValueRef := aArgs[unhidden].GetReferenceToRawData;
  2584. end else
  2585. args[i].ValueRef := aArgs[unhidden].GetReferenceToRawData;
  2586. Inc(unhidden);
  2587. end;
  2588. end;
  2589. flags := [];
  2590. if aStatic then
  2591. Include(flags, fcfStatic);
  2592. mgr.Invoke(aCodeAddress, args, aCallConv, restype, resptr, flags);
  2593. end;
  2594. function CreateCallbackProc(aHandler: TFunctionCallProc; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  2595. begin
  2596. if not Assigned(FuncCallMgr[aCallConv].CreateCallbackProc) then
  2597. raise ENotImplemented.Create(SErrCallbackNotImplemented);
  2598. if not Assigned(aHandler) then
  2599. raise EArgumentNilException.Create(SErrCallbackHandlerNil);
  2600. Result := FuncCallMgr[aCallConv].CreateCallbackProc(aHandler, aCallConv, aArgs, aResultType, aFlags, aContext);
  2601. end;
  2602. function CreateCallbackMethod(aHandler: TFunctionCallMethod; aCallConv: TCallConv; aArgs: array of TFunctionCallParameterInfo; aResultType: PTypeInfo; aFlags: TFunctionCallFlags; aContext: Pointer): TFunctionCallCallback;
  2603. begin
  2604. if not Assigned(FuncCallMgr[aCallConv].CreateCallbackMethod) then
  2605. raise ENotImplemented.Create(SErrCallbackNotImplemented);
  2606. if not Assigned(aHandler) then
  2607. raise EArgumentNilException.Create(SErrCallbackHandlerNil);
  2608. Result := FuncCallMgr[aCallConv].CreateCallbackMethod(aHandler, aCallConv, aArgs, aResultType, aFlags, aContext);
  2609. end;
  2610. function IsManaged(TypeInfo: PTypeInfo): boolean;
  2611. begin
  2612. if Assigned(TypeInfo) then
  2613. case TypeInfo^.Kind of
  2614. tkAString,
  2615. tkLString,
  2616. tkWString,
  2617. tkUString,
  2618. tkInterface,
  2619. tkVariant,
  2620. tkDynArray : Result := true;
  2621. tkArray : Result := IsManaged(GetTypeData(TypeInfo)^.ArrayData.ElType);
  2622. tkRecord,
  2623. tkObject :
  2624. with GetTypeData(TypeInfo)^.RecInitData^ do
  2625. Result := (ManagedFieldCount > 0) or Assigned(ManagementOp);
  2626. else
  2627. Result := false;
  2628. end
  2629. else
  2630. Result := false;
  2631. end;
  2632. function IsBoolType(ATypeInfo: PTypeInfo): Boolean;
  2633. begin
  2634. Result:=(ATypeInfo=TypeInfo(Boolean)) or
  2635. (ATypeInfo=TypeInfo(ByteBool)) or
  2636. (ATypeInfo=TypeInfo(WordBool)) or
  2637. (ATypeInfo=TypeInfo(LongBool));
  2638. end;
  2639. {$ifndef InLazIDE}
  2640. generic function OpenArrayToDynArrayValue<T>(constref aArray: array of T): TValue;
  2641. var
  2642. arr: specialize TArray<T>;
  2643. i: SizeInt;
  2644. begin
  2645. SetLength(arr, Length(aArray));
  2646. for i := 0 to High(aArray) do
  2647. arr[i] := aArray[i];
  2648. Result := TValue.specialize From<specialize TArray<T>>(arr);
  2649. end;
  2650. {$endif}
  2651. function ArrayOfConstToTValueArray(const aValues: array of const): TValueArray;
  2652. var
  2653. I,Len: Integer;
  2654. begin
  2655. Len:=Length(aValues);
  2656. SetLength(Result,Len);
  2657. for I:=0 to Len-1 do
  2658. Result[I]:=aValues[I];
  2659. end;
  2660. { TRttiPointerType }
  2661. function TRttiPointerType.GetReferredType: TRttiType;
  2662. begin
  2663. Result := GRttiPool.GetType(FTypeData^.RefType);
  2664. end;
  2665. { TRttiArrayType }
  2666. function TRttiArrayType.GetDimensionCount: SizeUInt;
  2667. begin
  2668. Result := FTypeData^.ArrayData.DimCount;
  2669. end;
  2670. function TRttiArrayType.GetDimension(aIndex: SizeInt): TRttiType;
  2671. begin
  2672. if aIndex >= FTypeData^.ArrayData.DimCount then
  2673. raise ERtti.CreateFmt(SErrDimensionOutOfRange, [aIndex, FTypeData^.ArrayData.DimCount]);
  2674. Result := GRttiPool.GetType(FTypeData^.ArrayData.Dims[Byte(aIndex)]);
  2675. end;
  2676. function TRttiArrayType.GetElementType: TRttiType;
  2677. begin
  2678. Result := GRttiPool.GetType(FTypeData^.ArrayData.ElType);
  2679. end;
  2680. function TRttiArrayType.GetTotalElementCount: SizeInt;
  2681. begin
  2682. Result := FTypeData^.ArrayData.ElCount;
  2683. end;
  2684. { TRttiDynamicArrayType }
  2685. function TRttiDynamicArrayType.GetDeclaringUnitName: String;
  2686. begin
  2687. Result := FTypeData^.DynUnitName;
  2688. end;
  2689. function TRttiDynamicArrayType.GetElementSize: SizeUInt;
  2690. begin
  2691. Result := FTypeData^.elSize;
  2692. end;
  2693. function TRttiDynamicArrayType.GetElementType: TRttiType;
  2694. begin
  2695. Result := GRttiPool.GetType(FTypeData^.ElType2);
  2696. end;
  2697. function TRttiDynamicArrayType.GetOleAutoVarType: TVarType;
  2698. begin
  2699. Result := Word(FTypeData^.varType);
  2700. end;
  2701. { TRttiRefCountedInterfaceType }
  2702. function TRttiRefCountedInterfaceType.IntfData: PInterfaceData;
  2703. begin
  2704. Result := PInterfaceData(FTypeData);
  2705. end;
  2706. function TRttiRefCountedInterfaceType.MethodTable: PIntfMethodTable;
  2707. begin
  2708. Result := IntfData^.MethodTable;
  2709. end;
  2710. function TRttiRefCountedInterfaceType.GetIntfBaseType: TRttiInterfaceType;
  2711. var
  2712. context: TRttiContext;
  2713. begin
  2714. if not Assigned(IntfData^.Parent) then
  2715. Exit(Nil);
  2716. context := TRttiContext.Create;
  2717. try
  2718. Result := context.GetType(IntfData^.Parent^) as TRttiInterfaceType;
  2719. finally
  2720. context.Free;
  2721. end;
  2722. end;
  2723. function TRttiRefCountedInterfaceType.GetDeclaringUnitName: String;
  2724. begin
  2725. Result := IntfData^.UnitName;
  2726. end;
  2727. function TRttiRefCountedInterfaceType.GetGUID: TGUID;
  2728. begin
  2729. Result := IntfData^.GUID;
  2730. end;
  2731. function TRttiRefCountedInterfaceType.GetIntfFlags: TIntfFlags;
  2732. begin
  2733. Result := IntfData^.Flags;
  2734. end;
  2735. function TRttiRefCountedInterfaceType.GetIntfType: TInterfaceType;
  2736. begin
  2737. Result := itRefCounted;
  2738. end;
  2739. { TRttiRawInterfaceType }
  2740. function TRttiRawInterfaceType.IntfData: PInterfaceRawData;
  2741. begin
  2742. Result := PInterfaceRawData(FTypeData);
  2743. end;
  2744. function TRttiRawInterfaceType.MethodTable: PIntfMethodTable;
  2745. begin
  2746. { currently there is none! }
  2747. Result := Nil;
  2748. end;
  2749. function TRttiRawInterfaceType.GetIntfBaseType: TRttiInterfaceType;
  2750. var
  2751. context: TRttiContext;
  2752. begin
  2753. if not Assigned(IntfData^.Parent) then
  2754. Exit(Nil);
  2755. context := TRttiContext.Create;
  2756. try
  2757. Result := context.GetType(IntfData^.Parent^) as TRttiInterfaceType;
  2758. finally
  2759. context.Free;
  2760. end;
  2761. end;
  2762. function TRttiRawInterfaceType.GetDeclaringUnitName: String;
  2763. begin
  2764. Result := IntfData^.UnitName;
  2765. end;
  2766. function TRttiRawInterfaceType.GetGUID: TGUID;
  2767. begin
  2768. Result := IntfData^.IID;
  2769. end;
  2770. function TRttiRawInterfaceType.GetGUIDStr: String;
  2771. begin
  2772. Result := IntfData^.IIDStr;
  2773. end;
  2774. function TRttiRawInterfaceType.GetIntfFlags: TIntfFlags;
  2775. begin
  2776. Result := IntfData^.Flags;
  2777. end;
  2778. function TRttiRawInterfaceType.GetIntfType: TInterfaceType;
  2779. begin
  2780. Result := itRaw;
  2781. end;
  2782. { TRttiVmtMethodParameter }
  2783. function TRttiVmtMethodParameter.GetHandle: Pointer;
  2784. begin
  2785. Result := FVmtMethodParam;
  2786. end;
  2787. function TRttiVmtMethodParameter.GetName: String;
  2788. begin
  2789. Result := FVmtMethodParam^.Name;
  2790. end;
  2791. function TRttiVmtMethodParameter.GetFlags: TParamFlags;
  2792. begin
  2793. Result := FVmtMethodParam^.Flags;
  2794. end;
  2795. function TRttiVmtMethodParameter.GetParamType: TRttiType;
  2796. var
  2797. context: TRttiContext;
  2798. begin
  2799. if not Assigned(FVmtMethodParam^.ParamType) then
  2800. Exit(Nil);
  2801. context := TRttiContext.Create;
  2802. try
  2803. Result := context.GetType(FVmtMethodParam^.ParamType^);
  2804. finally
  2805. context.Free;
  2806. end;
  2807. end;
  2808. constructor TRttiVmtMethodParameter.Create(AVmtMethodParam: PVmtMethodParam);
  2809. begin
  2810. inherited Create;
  2811. FVmtMethodParam := AVmtMethodParam;
  2812. end;
  2813. { TRttiMethodTypeParameter }
  2814. function TRttiMethodTypeParameter.GetHandle: Pointer;
  2815. begin
  2816. Result := fHandle;
  2817. end;
  2818. function TRttiMethodTypeParameter.GetName: String;
  2819. begin
  2820. Result := fName;
  2821. end;
  2822. function TRttiMethodTypeParameter.GetFlags: TParamFlags;
  2823. begin
  2824. Result := fFlags;
  2825. end;
  2826. function TRttiMethodTypeParameter.GetParamType: TRttiType;
  2827. var
  2828. context: TRttiContext;
  2829. begin
  2830. context := TRttiContext.Create;
  2831. try
  2832. Result := context.GetType(FType);
  2833. finally
  2834. context.Free;
  2835. end;
  2836. end;
  2837. constructor TRttiMethodTypeParameter.Create(aHandle: Pointer; const aName: String; aFlags: TParamFlags; aType: PTypeInfo);
  2838. begin
  2839. fHandle := aHandle;
  2840. fName := aName;
  2841. fFlags := aFlags;
  2842. fType := aType;
  2843. end;
  2844. { TRttiIntfMethod }
  2845. function TRttiIntfMethod.GetHandle: Pointer;
  2846. begin
  2847. Result := FIntfMethodEntry;
  2848. end;
  2849. function TRttiIntfMethod.GetName: String;
  2850. begin
  2851. Result := FIntfMethodEntry^.Name;
  2852. end;
  2853. function TRttiIntfMethod.GetCallingConvention: TCallConv;
  2854. begin
  2855. Result := FIntfMethodEntry^.CC;
  2856. end;
  2857. function TRttiIntfMethod.GetCodeAddress: CodePointer;
  2858. begin
  2859. Result := Nil;
  2860. end;
  2861. function TRttiIntfMethod.GetDispatchKind: TDispatchKind;
  2862. begin
  2863. Result := dkInterface;
  2864. end;
  2865. function TRttiIntfMethod.GetHasExtendedInfo: Boolean;
  2866. begin
  2867. Result := True;
  2868. end;
  2869. function TRttiIntfMethod.GetIsClassMethod: Boolean;
  2870. begin
  2871. Result := False;
  2872. end;
  2873. function TRttiIntfMethod.GetIsConstructor: Boolean;
  2874. begin
  2875. Result := False;
  2876. end;
  2877. function TRttiIntfMethod.GetIsDestructor: Boolean;
  2878. begin
  2879. Result := False;
  2880. end;
  2881. function TRttiIntfMethod.GetIsStatic: Boolean;
  2882. begin
  2883. Result := False;
  2884. end;
  2885. function TRttiIntfMethod.GetMethodKind: TMethodKind;
  2886. begin
  2887. Result := FIntfMethodEntry^.Kind;
  2888. end;
  2889. function TRttiIntfMethod.GetReturnType: TRttiType;
  2890. var
  2891. context: TRttiContext;
  2892. begin
  2893. if not Assigned(FIntfMethodEntry^.ResultType) then
  2894. Exit(Nil);
  2895. context := TRttiContext.Create;
  2896. try
  2897. Result := context.GetType(FIntfMethodEntry^.ResultType^);
  2898. finally
  2899. context.Free;
  2900. end;
  2901. end;
  2902. function TRttiIntfMethod.GetVirtualIndex: SmallInt;
  2903. begin
  2904. Result := FIndex;
  2905. end;
  2906. constructor TRttiIntfMethod.Create(AParent: TRttiType; AIntfMethodEntry: PIntfMethodEntry; AIndex: SmallInt);
  2907. begin
  2908. inherited Create(AParent);
  2909. FIntfMethodEntry := AIntfMethodEntry;
  2910. FIndex := AIndex;
  2911. end;
  2912. function TRttiIntfMethod.GetParameters(aWithHidden: Boolean): TRttiParameterArray;
  2913. var
  2914. param: PVmtMethodParam;
  2915. total, visible: SizeInt;
  2916. context: TRttiContext;
  2917. obj: TRttiObject;
  2918. begin
  2919. if aWithHidden and (Length(FParamsAll) > 0) then
  2920. Exit(FParamsAll);
  2921. if not aWithHidden and (Length(FParams) > 0) then
  2922. Exit(FParams);
  2923. if FIntfMethodEntry^.ParamCount = 0 then
  2924. Exit(Nil);
  2925. SetLength(FParams, FIntfMethodEntry^.ParamCount);
  2926. SetLength(FParamsAll, FIntfMethodEntry^.ParamCount);
  2927. context := TRttiContext.Create;
  2928. try
  2929. total := 0;
  2930. visible := 0;
  2931. param := FIntfMethodEntry^.Param[0];
  2932. while total < FIntfMethodEntry^.ParamCount do begin
  2933. obj := context.GetByHandle(param);
  2934. if Assigned(obj) then
  2935. FParamsAll[total] := obj as TRttiVmtMethodParameter
  2936. else begin
  2937. FParamsAll[total] := TRttiVmtMethodParameter.Create(param);
  2938. context.AddObject(FParamsAll[total]);
  2939. end;
  2940. if not (pfHidden in param^.Flags) then begin
  2941. FParams[visible] := FParamsAll[total];
  2942. Inc(visible);
  2943. end;
  2944. param := param^.Next;
  2945. Inc(total);
  2946. end;
  2947. if visible <> total then
  2948. SetLength(FParams, visible);
  2949. finally
  2950. context.Free;
  2951. end;
  2952. if aWithHidden then
  2953. Result := FParamsAll
  2954. else
  2955. Result := FParams;
  2956. end;
  2957. { TRttiInt64Type }
  2958. function TRttiInt64Type.GetMaxValue: Int64;
  2959. begin
  2960. Result := FTypeData^.MaxInt64Value;
  2961. end;
  2962. function TRttiInt64Type.GetMinValue: Int64;
  2963. begin
  2964. Result := FTypeData^.MinInt64Value;
  2965. end;
  2966. function TRttiInt64Type.GetUnsigned: Boolean;
  2967. begin
  2968. Result := FTypeData^.OrdType = otUQWord;
  2969. end;
  2970. function TRttiInt64Type.GetTypeSize: integer;
  2971. begin
  2972. Result := SizeOf(QWord);
  2973. end;
  2974. { TRttiOrdinalType }
  2975. function TRttiOrdinalType.GetMaxValue: LongInt;
  2976. begin
  2977. Result := FTypeData^.MaxValue;
  2978. end;
  2979. function TRttiOrdinalType.GetMinValue: LongInt;
  2980. begin
  2981. Result := FTypeData^.MinValue;
  2982. end;
  2983. function TRttiOrdinalType.GetOrdType: TOrdType;
  2984. begin
  2985. Result := FTypeData^.OrdType;
  2986. end;
  2987. function TRttiOrdinalType.GetTypeSize: Integer;
  2988. begin
  2989. case OrdType of
  2990. otSByte,
  2991. otUByte:
  2992. Result := SizeOf(Byte);
  2993. otSWord,
  2994. otUWord:
  2995. Result := SizeOf(Word);
  2996. otSLong,
  2997. otULong:
  2998. Result := SizeOf(LongWord);
  2999. otSQWord,
  3000. otUQWord:
  3001. Result := SizeOf(QWord);
  3002. end;
  3003. end;
  3004. { TRttiFloatType }
  3005. function TRttiFloatType.GetFloatType: TFloatType;
  3006. begin
  3007. result := FTypeData^.FloatType;
  3008. end;
  3009. function TRttiFloatType.GetTypeSize: integer;
  3010. begin
  3011. case FloatType of
  3012. ftSingle:
  3013. Result := SizeOf(Single);
  3014. ftDouble:
  3015. Result := SizeOf(Double);
  3016. ftExtended:
  3017. Result := SizeOf(Extended);
  3018. ftComp:
  3019. Result := SizeOf(Comp);
  3020. ftCurr:
  3021. Result := SizeOf(Currency);
  3022. end;
  3023. end;
  3024. { TRttiParameter }
  3025. function TRttiParameter.ToString: String;
  3026. var
  3027. f: TParamFlags;
  3028. n: String;
  3029. t: TRttiType;
  3030. begin
  3031. if FString = '' then begin
  3032. f := Flags;
  3033. if pfVar in f then
  3034. FString := 'var'
  3035. else if pfConst in f then
  3036. FString := 'const'
  3037. else if pfOut in f then
  3038. FString := 'out'
  3039. else if pfConstRef in f then
  3040. FString := 'constref';
  3041. if FString <> '' then
  3042. FString := FString + ' ';
  3043. n := Name;
  3044. if n = '' then
  3045. n := '<unknown>';
  3046. FString := FString + n;
  3047. t := ParamType;
  3048. if Assigned(t) then begin
  3049. FString := FString + ': ';
  3050. if pfArray in flags then
  3051. FString := 'array of ';
  3052. FString := FString + t.Name;
  3053. end;
  3054. end;
  3055. Result := FString;
  3056. end;
  3057. { TMethodImplementation }
  3058. function TMethodImplementation.GetCodeAddress: CodePointer;
  3059. begin
  3060. Result := fLowLevelCallback.CodeAddress;
  3061. end;
  3062. procedure TMethodImplementation.InitArgs;
  3063. var
  3064. i, refargs: SizeInt;
  3065. begin
  3066. i := 0;
  3067. refargs := 0;
  3068. SetLength(fRefArgs, Length(fArgs));
  3069. while i < Length(fArgs) do begin
  3070. if (fArgs[i].ParamFlags * [pfVar, pfOut] <> []) and not (pfHidden in fArgs[i].ParamFlags) then begin
  3071. fRefArgs[refargs] := fArgLen;
  3072. Inc(refargs);
  3073. end;
  3074. if pfArray in fArgs[i].ParamFlags then begin
  3075. Inc(i);
  3076. if (i = Length(fArgs)) or not (pfHigh in fArgs[i].ParamFlags) then
  3077. raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
  3078. Inc(fArgLen);
  3079. end else if not (pfHidden in fArgs[i].ParamFlags) or (pfSelf in fArgs[i].ParamFlags) then
  3080. Inc(fArgLen)
  3081. else if (pfResult in fArgs[i].ParamFlags) then
  3082. fResult := fArgs[i].ParamType;
  3083. Inc(i);
  3084. end;
  3085. SetLength(fRefArgs, refargs);
  3086. end;
  3087. procedure TMethodImplementation.HandleCallback(const aArgs: specialize TArray<Pointer>; aResult: Pointer; aContext: Pointer);
  3088. var
  3089. i, argidx, validx: SizeInt;
  3090. args: TValueArray;
  3091. res: TValue;
  3092. begin
  3093. Assert(fArgLen = Length(aArgs), 'Length of arguments does not match');
  3094. SetLength(args, fArgLen);
  3095. argidx := 0;
  3096. validx := 0;
  3097. i := 0;
  3098. while i < Length(fArgs) do begin
  3099. if pfArray in fArgs[i].ParamFlags then begin
  3100. Inc(validx);
  3101. Inc(i);
  3102. Assert((i < Length(fArgs)) and (pfHigh in fArgs[i].ParamFlags), 'Expected high parameter after open array parameter');
  3103. TValue.MakeOpenArray(aArgs[validx - 1], SizeInt(aArgs[validx]), fArgs[i].ParamType, args[argidx]);
  3104. Inc(argidx);
  3105. Inc(validx);
  3106. end else if not (pfHidden in fArgs[i].ParamFlags) or (pfSelf in fArgs[i].ParamFlags) then begin
  3107. if Assigned(fArgs[i].ParamType) then
  3108. TValue.Make(aArgs[validx], fArgs[i].ParamType, args[argidx])
  3109. else
  3110. TValue.Make(@aArgs[validx], TypeInfo(Pointer), args[argidx]);
  3111. Inc(argidx);
  3112. Inc(validx);
  3113. end;
  3114. Inc(i);
  3115. end;
  3116. if Assigned(fCallbackMethod) then
  3117. fCallbackMethod(aContext, args, res)
  3118. else
  3119. fCallbackProc(aContext, args, res);
  3120. { copy back var/out parameters }
  3121. for i := 0 to High(fRefArgs) do begin
  3122. args[fRefArgs[i]].ExtractRawData(aArgs[fRefArgs[i]]);
  3123. end;
  3124. if Assigned(fResult) then
  3125. res.ExtractRawData(aResult);
  3126. end;
  3127. constructor TMethodImplementation.Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackMethod);
  3128. begin
  3129. fCC := aCC;
  3130. fArgs := aArgs;
  3131. fResult := aResult;
  3132. fFlags := aFlags;
  3133. fCallbackMethod := aCallback;
  3134. InitArgs;
  3135. fLowLevelCallback := CreateCallbackMethod(@HandleCallback, fCC, aArgs, aResult, aFlags, aUserData);
  3136. if not Assigned(fLowLevelCallback) then
  3137. raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
  3138. end;
  3139. constructor TMethodImplementation.Create(aCC: TCallConv; aArgs: specialize TArray<TFunctionCallParameterInfo>; aResult: PTypeInfo; aFlags: TFunctionCallFlags; aUserData: Pointer; aCallback: TMethodImplementationCallbackProc);
  3140. begin
  3141. fCC := aCC;
  3142. fArgs := aArgs;
  3143. fResult := aResult;
  3144. fFlags := aFlags;
  3145. fCallbackProc := aCallback;
  3146. InitArgs;
  3147. fLowLevelCallback := CreateCallbackMethod(@HandleCallback, fCC, aArgs, aResult, aFlags, aUserData);
  3148. if not Assigned(fLowLevelCallback) then
  3149. raise EInsufficientRtti.Create(SErrMethodImplCreateFailed);
  3150. end;
  3151. constructor TMethodImplementation.Create;
  3152. begin
  3153. raise EInvalidOpException.Create(SErrMethodImplCreateNoArg);
  3154. end;
  3155. destructor TMethodImplementation.Destroy;
  3156. begin
  3157. fLowLevelCallback.Free;
  3158. inherited Destroy;
  3159. end;
  3160. { TRttiMethod }
  3161. function TRttiMethod.GetHasExtendedInfo: Boolean;
  3162. begin
  3163. Result := False;
  3164. end;
  3165. function TRttiMethod.GetFlags: TFunctionCallFlags;
  3166. begin
  3167. Result := [];
  3168. if IsStatic then
  3169. Include(Result, fcfStatic);
  3170. end;
  3171. function TRttiMethod.GetParameters: TRttiParameterArray;
  3172. begin
  3173. Result := GetParameters(False);
  3174. end;
  3175. function TRttiMethod.ToString: String;
  3176. var
  3177. ret: TRttiType;
  3178. n: String;
  3179. params: TRttiParameterArray;
  3180. i: LongInt;
  3181. begin
  3182. if FString = '' then begin
  3183. n := Name;
  3184. if n = '' then
  3185. n := '<unknown>';
  3186. if not HasExtendedInfo then begin
  3187. FString := 'method ' + n;
  3188. end else begin
  3189. ret := ReturnType;
  3190. if IsClassMethod then
  3191. FString := 'class ';
  3192. if IsConstructor then
  3193. FString := FString + 'constructor'
  3194. else if IsDestructor then
  3195. FString := FString + 'destructor'
  3196. else if Assigned(ret) then
  3197. FString := FString + 'function'
  3198. else
  3199. FString := FString + 'procedure';
  3200. FString := FString + ' ' + n;
  3201. params := GetParameters;
  3202. if Length(params) > 0 then begin
  3203. FString := FString + '(';
  3204. for i := 0 to High(params) do begin
  3205. if i > 0 then
  3206. FString := FString + '; ';
  3207. FString := FString + params[i].ToString;
  3208. end;
  3209. FString := FString + ')';
  3210. end;
  3211. if Assigned(ret) then
  3212. FString := FString + ': ' + ret.Name;
  3213. if IsStatic then
  3214. FString := FString + '; static';
  3215. end;
  3216. end;
  3217. Result := FString;
  3218. end;
  3219. function TRttiMethod.Invoke(aInstance: TObject; const aArgs: array of TValue): TValue;
  3220. var
  3221. instance: TValue;
  3222. begin
  3223. TValue.Make(@aInstance, TypeInfo(TObject), instance);
  3224. Result := Invoke(instance, aArgs);
  3225. end;
  3226. function TRttiMethod.Invoke(aInstance: TClass; const aArgs: array of TValue): TValue;
  3227. var
  3228. instance: TValue;
  3229. begin
  3230. TValue.Make(@aInstance, TypeInfo(TClass), instance);
  3231. Result := Invoke(instance, aArgs);
  3232. end;
  3233. function TRttiMethod.Invoke(aInstance: TValue; const aArgs: array of TValue): TValue;
  3234. var
  3235. addr: CodePointer;
  3236. vmt: PCodePointer;
  3237. begin
  3238. if not HasExtendedInfo then
  3239. raise EInvocationError.Create(SErrInvokeInsufficientRtti);
  3240. if IsStatic and not aInstance.IsEmpty then
  3241. raise EInvocationError.CreateFmt(SErrInvokeStaticNoSelf, [Name]);
  3242. if not IsStatic and aInstance.IsEmpty then
  3243. raise EInvocationError.CreateFmt(SErrInvokeNotStaticNeedsSelf, [Name]);
  3244. if not IsStatic and IsClassMethod and not aInstance.IsClass then
  3245. raise EInvocationError.CreateFmt(SErrInvokeClassMethodClassSelf, [Name]);
  3246. addr := Nil;
  3247. if IsStatic then
  3248. addr := CodeAddress
  3249. else begin
  3250. vmt := Nil;
  3251. if aInstance.Kind in [tkInterface, tkInterfaceRaw] then
  3252. vmt := PCodePointer(PPPointer(aInstance.GetReferenceToRawData)^^);
  3253. { ToDo }
  3254. if Assigned(vmt) then
  3255. addr := vmt[VirtualIndex];
  3256. end;
  3257. Result := {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Rtti.Invoke(Name, addr, CallingConvention, IsStatic, aInstance, aArgs, GetParameters(True), ReturnType);
  3258. end;
  3259. function TRttiMethod.CreateImplementation(aUserData: Pointer; aCallback: TMethodImplementationCallbackMethod): TMethodImplementation;
  3260. var
  3261. params: TRttiParameterArray;
  3262. args: specialize TArray<TFunctionCallParameterInfo>;
  3263. res: PTypeInfo;
  3264. restype: TRttiType;
  3265. resinparam: Boolean;
  3266. i: SizeInt;
  3267. begin
  3268. if not Assigned(aCallback) then
  3269. raise EArgumentNilException.Create(SErrMethodImplNoCallback);
  3270. resinparam := False;
  3271. params := GetParameters(True);
  3272. SetLength(args, Length(params));
  3273. for i := 0 to High(params) do begin
  3274. if Assigned(params[i].ParamType) then
  3275. args[i].ParamType := params[i].ParamType.FTypeInfo
  3276. else
  3277. args[i].ParamType := Nil;
  3278. args[i].ParamFlags := params[i].Flags;
  3279. args[i].ParaLocs := Nil;
  3280. if pfResult in params[i].Flags then
  3281. resinparam := True;
  3282. end;
  3283. restype := GetReturnType;
  3284. if Assigned(restype) and not resinparam then
  3285. res := restype.FTypeInfo
  3286. else
  3287. res := Nil;
  3288. Result := TMethodImplementation.Create(GetCallingConvention, args, res, GetFlags, aUserData, aCallback);
  3289. end;
  3290. function TRttiMethod.CreateImplementation(aUserData: Pointer; aCallback: TMethodImplementationCallbackProc): TMethodImplementation;
  3291. var
  3292. params: TRttiParameterArray;
  3293. args: specialize TArray<TFunctionCallParameterInfo>;
  3294. res: PTypeInfo;
  3295. restype: TRttiType;
  3296. resinparam: Boolean;
  3297. i: SizeInt;
  3298. begin
  3299. if not Assigned(aCallback) then
  3300. raise EArgumentNilException.Create(SErrMethodImplNoCallback);
  3301. resinparam := False;
  3302. params := GetParameters(True);
  3303. SetLength(args, Length(params));
  3304. for i := 0 to High(params) do begin
  3305. if Assigned(params[i].ParamType) then
  3306. args[i].ParamType := params[i].ParamType.FTypeInfo
  3307. else
  3308. args[i].ParamType := Nil;
  3309. args[i].ParamFlags := params[i].Flags;
  3310. args[i].ParaLocs := Nil;
  3311. if pfResult in params[i].Flags then
  3312. resinparam := True;
  3313. end;
  3314. restype := GetReturnType;
  3315. if Assigned(restype) and not resinparam then
  3316. res := restype.FTypeInfo
  3317. else
  3318. res := Nil;
  3319. Result := TMethodImplementation.Create(GetCallingConvention, args, res, GetFlags, aUserData, aCallback);
  3320. end;
  3321. { TRttiInvokableType }
  3322. function TRttiInvokableType.GetParameters: TRttiParameterArray;
  3323. begin
  3324. Result := GetParameters(False);
  3325. end;
  3326. function TRttiInvokableType.CreateImplementation(aCallback: TCallbackMethod): TMethodImplementation;
  3327. var
  3328. params: TRttiParameterArray;
  3329. args: specialize TArray<TFunctionCallParameterInfo>;
  3330. res: PTypeInfo;
  3331. restype: TRttiType;
  3332. resinparam: Boolean;
  3333. i: SizeInt;
  3334. begin
  3335. if not Assigned(aCallback) then
  3336. raise EArgumentNilException.Create(SErrMethodImplNoCallback);
  3337. resinparam := False;
  3338. params := GetParameters(True);
  3339. SetLength(args, Length(params));
  3340. for i := 0 to High(params) do begin
  3341. if Assigned(params[i].ParamType) then
  3342. args[i].ParamType := params[i].ParamType.FTypeInfo
  3343. else
  3344. args[i].ParamType := Nil;
  3345. args[i].ParamFlags := params[i].Flags;
  3346. args[i].ParaLocs := Nil;
  3347. if pfResult in params[i].Flags then
  3348. resinparam := True;
  3349. end;
  3350. restype := GetReturnType;
  3351. if Assigned(restype) and not resinparam then
  3352. res := restype.FTypeInfo
  3353. else
  3354. res := Nil;
  3355. Result := TMethodImplementation.Create(GetCallingConvention, args, res, GetFlags, Self, TMethodImplementationCallbackMethod(aCallback));
  3356. end;
  3357. function TRttiInvokableType.CreateImplementation(aCallback: TCallbackProc): TMethodImplementation;
  3358. var
  3359. params: TRttiParameterArray;
  3360. args: specialize TArray<TFunctionCallParameterInfo>;
  3361. res: PTypeInfo;
  3362. restype: TRttiType;
  3363. resinparam: Boolean;
  3364. i: SizeInt;
  3365. begin
  3366. if not Assigned(aCallback) then
  3367. raise EArgumentNilException.Create(SErrMethodImplNoCallback);
  3368. resinparam := False;
  3369. params := GetParameters(True);
  3370. SetLength(args, Length(params));
  3371. for i := 0 to High(params) do begin
  3372. if Assigned(params[i].ParamType) then
  3373. args[i].ParamType := params[i].ParamType.FTypeInfo
  3374. else
  3375. args[i].ParamType := Nil;
  3376. args[i].ParamFlags := params[i].Flags;
  3377. args[i].ParaLocs := Nil;
  3378. if pfResult in params[i].Flags then
  3379. resinparam := True;
  3380. end;
  3381. restype := GetReturnType;
  3382. if Assigned(restype) and not resinparam then
  3383. res := restype.FTypeInfo
  3384. else
  3385. res := Nil;
  3386. Result := TMethodImplementation.Create(GetCallingConvention, args, res, GetFlags, Self, TMethodImplementationCallbackProc(aCallback));
  3387. end;
  3388. function TRttiInvokableType.ToString: string;
  3389. var
  3390. P : TRTTIParameter;
  3391. A : TRTTIParameterArray;
  3392. I : integer;
  3393. RT : TRttiType;
  3394. begin
  3395. RT:=GetReturnType;
  3396. if RT=nil then
  3397. Result:=name+' = procedure ('
  3398. else
  3399. Result:=name+' = function (';
  3400. A:=GetParameters(False);
  3401. for I:=0 to Length(a)-1 do
  3402. begin
  3403. P:=A[I];
  3404. if I>0 then
  3405. Result:=Result+'; ';
  3406. Result:=Result+P.Name;
  3407. if Assigned(P.ParamType) then
  3408. Result:=Result+' : '+P.ParamType.Name;
  3409. end;
  3410. result:=Result+')';
  3411. if Assigned(RT) then
  3412. Result:=Result+' : '+RT.Name;
  3413. end;
  3414. { TRttiMethodType }
  3415. function TRttiMethodType.GetParameters(aWithHidden: Boolean): TRttiParameterArray;
  3416. type
  3417. TParamInfo = record
  3418. Handle: Pointer;
  3419. Flags: TParamFlags;
  3420. Name: String;
  3421. end;
  3422. PParamFlags = ^TParamFlags;
  3423. PCallConv = ^TCallConv;
  3424. PPPTypeInfo = ^PPTypeInfo;
  3425. var
  3426. infos: array of TParamInfo;
  3427. total, visible, i: SizeInt;
  3428. ptr: PByte;
  3429. paramtypes: PPPTypeInfo;
  3430. paramtype: PTypeInfo;
  3431. context: TRttiContext;
  3432. obj: TRttiObject;
  3433. begin
  3434. if aWithHidden and (Length(FParamsAll) > 0) then
  3435. Exit(FParamsAll);
  3436. if not aWithHidden and (Length(FParams) > 0) then
  3437. Exit(FParams);
  3438. ptr := @FTypeData^.ParamList[0];
  3439. visible := 0;
  3440. total := 0;
  3441. if FTypeData^.ParamCount > 0 then begin
  3442. SetLength(infos, FTypeData^.ParamCount);
  3443. while total < FTypeData^.ParamCount do begin
  3444. { align }
  3445. ptr := AlignTParamFlags(ptr);
  3446. infos[total].Handle := ptr;
  3447. infos[total].Flags := PParamFlags(ptr)^;
  3448. Inc(ptr, SizeOf(TParamFlags));
  3449. { handle name }
  3450. infos[total].Name := PShortString(ptr)^;
  3451. Inc(ptr, ptr^ + SizeOf(Byte));
  3452. { skip type name }
  3453. Inc(ptr, ptr^ + SizeOf(Byte));
  3454. if not (pfHidden in infos[total].Flags) then
  3455. Inc(visible);
  3456. Inc(total);
  3457. end;
  3458. end;
  3459. if FTypeData^.MethodKind in [mkFunction, mkClassFunction] then begin
  3460. { skip return type name }
  3461. ptr := AlignToPtr(PByte(ptr) + ptr^ + SizeOf(Byte));
  3462. { handle return type }
  3463. FReturnType := GRttiPool.GetType(PPPTypeInfo(ptr)^^);
  3464. Inc(ptr, SizeOf(PPTypeInfo));
  3465. end;
  3466. { handle calling convention }
  3467. FCallConv := PCallConv(ptr)^;
  3468. Inc(ptr, SizeOf(TCallConv));
  3469. SetLength(FParamsAll, FTypeData^.ParamCount);
  3470. SetLength(FParams, visible);
  3471. if FTypeData^.ParamCount > 0 then begin
  3472. context := TRttiContext.Create;
  3473. try
  3474. paramtypes := PPPTypeInfo(AlignTypeData(ptr));
  3475. visible := 0;
  3476. for i := 0 to FTypeData^.ParamCount - 1 do begin
  3477. obj := context.GetByHandle(infos[i].Handle);
  3478. if Assigned(obj) then
  3479. FParamsAll[i] := obj as TRttiMethodTypeParameter
  3480. else begin
  3481. if Assigned(paramtypes[i]) then
  3482. paramtype := paramtypes[i]^
  3483. else
  3484. paramtype := Nil;
  3485. FParamsAll[i] := TRttiMethodTypeParameter.Create(infos[i].Handle, infos[i].Name, infos[i].Flags, paramtype);
  3486. context.AddObject(FParamsAll[i]);
  3487. end;
  3488. if not (pfHidden in infos[i].Flags) then begin
  3489. FParams[visible] := FParamsAll[i];
  3490. Inc(visible);
  3491. end;
  3492. end;
  3493. finally
  3494. context.Free;
  3495. end;
  3496. end;
  3497. if aWithHidden then
  3498. Result := FParamsAll
  3499. else
  3500. Result := FParams;
  3501. end;
  3502. function TRttiMethodType.GetCallingConvention: TCallConv;
  3503. begin
  3504. { the calling convention is located after the parameters, so get the parameters
  3505. which will also initialize the calling convention }
  3506. GetParameters(True);
  3507. Result := FCallConv;
  3508. end;
  3509. function TRttiMethodType.GetReturnType: TRttiType;
  3510. begin
  3511. if FTypeData^.MethodKind in [mkFunction, mkClassFunction] then begin
  3512. { the return type is located after the parameters, so get the parameters
  3513. which will also initialize the return type }
  3514. GetParameters(True);
  3515. Result := FReturnType;
  3516. end else
  3517. Result := Nil;
  3518. end;
  3519. function TRttiMethodType.GetFlags: TFunctionCallFlags;
  3520. begin
  3521. Result := [];
  3522. end;
  3523. function TRttiMethodType.ToString: string;
  3524. begin
  3525. Result:=Inherited ToString;
  3526. Result:=Result+' of object';
  3527. end;
  3528. function TRttiMethodType.Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue;
  3529. var
  3530. method: PMethod;
  3531. inst: TValue;
  3532. begin
  3533. if aCallable.Kind <> tkMethod then
  3534. raise EInvocationError.CreateFmt(SErrInvokeCallableNotMethod, [Name]);
  3535. method := PMethod(aCallable.GetReferenceToRawData);
  3536. { by using a pointer we can also use this for non-class instance methods }
  3537. TValue.Make(@method^.Data, PTypeInfo(TypeInfo(Pointer)), inst);
  3538. Result := {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Rtti.Invoke(Name, method^.Code, CallingConvention, False, inst, aArgs, GetParameters(True), ReturnType);
  3539. end;
  3540. { TRttiProcedureType }
  3541. function TRttiProcedureType.GetParameters(aWithHidden: Boolean): TRttiParameterArray;
  3542. var
  3543. visible, i: SizeInt;
  3544. param: PProcedureParam;
  3545. obj: TRttiObject;
  3546. context: TRttiContext;
  3547. begin
  3548. if aWithHidden and (Length(FParamsAll) > 0) then
  3549. Exit(FParamsAll);
  3550. if not aWithHidden and (Length(FParams) > 0) then
  3551. Exit(FParams);
  3552. if FTypeData^.ProcSig.ParamCount = 0 then
  3553. Exit(Nil);
  3554. SetLength(FParamsAll, FTypeData^.ProcSig.ParamCount);
  3555. SetLength(FParams, FTypeData^.ProcSig.ParamCount);
  3556. context := TRttiContext.Create;
  3557. try
  3558. param := AlignToPtr(PProcedureParam(@FTypeData^.ProcSig.ParamCount + SizeOf(FTypeData^.ProcSig.ParamCount)));
  3559. visible := 0;
  3560. for i := 0 to FTypeData^.ProcSig.ParamCount - 1 do begin
  3561. obj := context.GetByHandle(param);
  3562. if Assigned(obj) then
  3563. FParamsAll[i] := obj as TRttiMethodTypeParameter
  3564. else begin
  3565. FParamsAll[i] := TRttiMethodTypeParameter.Create(param, param^.Name, param^.ParamFlags, param^.ParamType);
  3566. context.AddObject(FParamsAll[i]);
  3567. end;
  3568. if not (pfHidden in param^.ParamFlags) then begin
  3569. FParams[visible] := FParamsAll[i];
  3570. Inc(visible);
  3571. end;
  3572. param := PProcedureParam(AlignToPtr(PByte(@param^.Name) + Length(param^.Name) + SizeOf(param^.Name[0])));
  3573. end;
  3574. SetLength(FParams, visible);
  3575. finally
  3576. context.Free;
  3577. end;
  3578. if aWithHidden then
  3579. Result := FParamsAll
  3580. else
  3581. Result := FParams;
  3582. end;
  3583. function TRttiProcedureType.GetCallingConvention: TCallConv;
  3584. begin
  3585. Result := FTypeData^.ProcSig.CC;
  3586. end;
  3587. function TRttiProcedureType.GetReturnType: TRttiType;
  3588. var
  3589. context: TRttiContext;
  3590. begin
  3591. if not Assigned(FTypeData^.ProcSig.ResultTypeRef) then
  3592. Exit(Nil);
  3593. context := TRttiContext.Create;
  3594. try
  3595. Result := context.GetType(FTypeData^.ProcSig.ResultTypeRef^);
  3596. finally
  3597. context.Free;
  3598. end;
  3599. end;
  3600. function TRttiProcedureType.GetFlags: TFunctionCallFlags;
  3601. begin
  3602. Result := [fcfStatic];
  3603. end;
  3604. function TRttiProcedureType.Invoke(const aCallable: TValue; const aArgs: array of TValue): TValue;
  3605. begin
  3606. if aCallable.Kind <> tkProcVar then
  3607. raise EInvocationError.CreateFmt(SErrInvokeCallableNotProc, [Name]);
  3608. Result := {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Rtti.Invoke(Name, PCodePointer(aCallable.GetReferenceToRawData)^, CallingConvention, True, TValue.Empty, aArgs, GetParameters(True), ReturnType);
  3609. end;
  3610. { TRttiStringType }
  3611. function TRttiStringType.GetStringKind: TRttiStringKind;
  3612. begin
  3613. case TypeKind of
  3614. tkSString : result := skShortString;
  3615. tkLString : result := skAnsiString;
  3616. tkAString : result := skAnsiString;
  3617. tkUString : result := skUnicodeString;
  3618. tkWString : result := skWideString;
  3619. end;
  3620. end;
  3621. function TRttiAnsiStringType.GetCodePage: Word;
  3622. begin
  3623. Result:=FTypeData^.CodePage;
  3624. end;
  3625. { TRttiInterfaceType }
  3626. function TRttiInterfaceType.IntfMethodCount: Word;
  3627. var
  3628. parent: TRttiInterfaceType;
  3629. table: PIntfMethodTable;
  3630. begin
  3631. parent := GetIntfBaseType;
  3632. if Assigned(parent) then
  3633. Result := parent.IntfMethodCount
  3634. else
  3635. Result := 0;
  3636. table := MethodTable;
  3637. if Assigned(table) then
  3638. Inc(Result, table^.Count);
  3639. end;
  3640. function TRttiInterfaceType.GetBaseType: TRttiType;
  3641. begin
  3642. Result := GetIntfBaseType;
  3643. end;
  3644. function TRttiInterfaceType.GetGUIDStr: String;
  3645. begin
  3646. Result := GUIDToString(GUID);
  3647. end;
  3648. function TRttiInterfaceType.GetDeclaredMethods: specialize TArray<TRttiMethod>;
  3649. var
  3650. methtable: PIntfMethodTable;
  3651. count, index: Word;
  3652. method: PIntfMethodEntry;
  3653. context: TRttiContext;
  3654. obj: TRttiObject;
  3655. parent: TRttiInterfaceType;
  3656. parentmethodcount: Word;
  3657. begin
  3658. if Assigned(fDeclaredMethods) then
  3659. Exit(fDeclaredMethods);
  3660. methtable := MethodTable;
  3661. if not Assigned(methtable) then
  3662. Exit(Nil);
  3663. if (methtable^.Count = 0) or (methtable^.RTTICount = $ffff) then
  3664. Exit(Nil);
  3665. parent := GetIntfBaseType;
  3666. if Assigned(parent) then
  3667. parentmethodcount := parent.IntfMethodCount
  3668. else
  3669. parentmethodcount := 0;
  3670. SetLength(fDeclaredMethods, methtable^.Count);
  3671. context := TRttiContext.Create;
  3672. try
  3673. method := methtable^.Method[0];
  3674. count := methtable^.Count;
  3675. while count > 0 do begin
  3676. index := methtable^.Count - count;
  3677. obj := context.GetByHandle(method);
  3678. if Assigned(obj) then
  3679. fDeclaredMethods[index] := obj as TRttiMethod
  3680. else begin
  3681. fDeclaredMethods[index] := TRttiIntfMethod.Create(Self, method, parentmethodcount + index);
  3682. context.AddObject(fDeclaredMethods[index]);
  3683. end;
  3684. method := method^.Next;
  3685. Dec(count);
  3686. end;
  3687. finally
  3688. context.Free;
  3689. end;
  3690. Result := fDeclaredMethods;
  3691. end;
  3692. { TRttiInstanceType }
  3693. function TRttiInstanceType.GetMetaClassType: TClass;
  3694. begin
  3695. result := FTypeData^.ClassType;
  3696. end;
  3697. function TRttiInstanceType.GetDeclaringUnitName: string;
  3698. begin
  3699. result := FTypeData^.UnitName;
  3700. end;
  3701. function TRttiInstanceType.GetBaseType: TRttiType;
  3702. var
  3703. AContext: TRttiContext;
  3704. begin
  3705. AContext := TRttiContext.Create;
  3706. try
  3707. result := AContext.GetType(FTypeData^.ParentInfo);
  3708. finally
  3709. AContext.Free;
  3710. end;
  3711. end;
  3712. function TRttiInstanceType.GetIsInstance: boolean;
  3713. begin
  3714. Result:=True;
  3715. end;
  3716. function TRttiInstanceType.GetTypeSize: integer;
  3717. begin
  3718. Result:=sizeof(TObject);
  3719. end;
  3720. function TRttiInstanceType.GetProperties: specialize TArray<TRttiProperty>;
  3721. var
  3722. TypeInfo: PTypeInfo;
  3723. TypeRttiType: TRttiType;
  3724. TD: PTypeData;
  3725. PPD: PPropData;
  3726. TP: PPropInfo;
  3727. Count: longint;
  3728. obj: TRttiObject;
  3729. begin
  3730. if not FPropertiesResolved then
  3731. begin
  3732. TypeInfo := FTypeInfo;
  3733. // Get the total properties count
  3734. SetLength(FProperties,FTypeData^.PropCount);
  3735. TypeRttiType:= self;
  3736. repeat
  3737. TD:=GetTypeData(TypeInfo);
  3738. // published properties count for this object
  3739. // skip the attribute-info if available
  3740. PPD := PClassData(TD)^.PropertyTable;
  3741. Count:=PPD^.PropCount;
  3742. // Now point TP to first propinfo record.
  3743. TP:=PPropInfo(@PPD^.PropList);
  3744. While Count>0 do
  3745. begin
  3746. // Don't overwrite properties with the same name
  3747. if FProperties[TP^.NameIndex]=nil then begin
  3748. obj := GRttiPool.GetByHandle(TP);
  3749. if Assigned(obj) then
  3750. FProperties[TP^.NameIndex] := obj as TRttiProperty
  3751. else begin
  3752. FProperties[TP^.NameIndex] := TRttiProperty.Create(TypeRttiType, TP);
  3753. GRttiPool.AddObject(FProperties[TP^.NameIndex]);
  3754. end;
  3755. end;
  3756. // Point to TP next propinfo record.
  3757. // Located at Name[Length(Name)+1] !
  3758. TP:=TP^.Next;
  3759. Dec(Count);
  3760. end;
  3761. TypeInfo:=TD^.Parentinfo;
  3762. TypeRttiType:= GRttiPool.GetType(TypeInfo);
  3763. until TypeInfo=nil;
  3764. end;
  3765. result := FProperties;
  3766. end;
  3767. { TRttiMember }
  3768. function TRttiMember.GetVisibility: TMemberVisibility;
  3769. begin
  3770. result := mvPublished;
  3771. end;
  3772. constructor TRttiMember.Create(AParent: TRttiType);
  3773. begin
  3774. inherited Create();
  3775. FParent := AParent;
  3776. end;
  3777. { TRttiProperty }
  3778. function TRttiProperty.GetPropertyType: TRttiType;
  3779. begin
  3780. result := GRttiPool.GetType(FPropInfo^.PropType);
  3781. end;
  3782. function TRttiProperty.GetIsReadable: boolean;
  3783. begin
  3784. result := assigned(FPropInfo^.GetProc);
  3785. end;
  3786. function TRttiProperty.GetIsWritable: boolean;
  3787. begin
  3788. result := assigned(FPropInfo^.SetProc);
  3789. end;
  3790. function TRttiProperty.GetVisibility: TMemberVisibility;
  3791. begin
  3792. // At this moment only pulished rtti-property-info is supported by fpc
  3793. result := mvPublished;
  3794. end;
  3795. function TRttiProperty.GetName: string;
  3796. begin
  3797. Result:=FPropInfo^.Name;
  3798. end;
  3799. function TRttiProperty.GetHandle: Pointer;
  3800. begin
  3801. Result := FPropInfo;
  3802. end;
  3803. constructor TRttiProperty.Create(AParent: TRttiType; APropInfo: PPropInfo);
  3804. begin
  3805. inherited Create(AParent);
  3806. FPropInfo := APropInfo;
  3807. end;
  3808. destructor TRttiProperty.Destroy;
  3809. var
  3810. attr: TCustomAttribute;
  3811. begin
  3812. for attr in FAttributes do
  3813. attr.Free;
  3814. inherited Destroy;
  3815. end;
  3816. function TRttiProperty.GetAttributes: TCustomAttributeArray;
  3817. var
  3818. i: SizeInt;
  3819. at: PAttributeTable;
  3820. begin
  3821. if not FAttributesResolved then
  3822. begin
  3823. at := FPropInfo^.AttributeTable;
  3824. if Assigned(at) then
  3825. begin
  3826. SetLength(FAttributes, at^.AttributeCount);
  3827. for i := 0 to High(FAttributes) do
  3828. FAttributes[i] := TCustomAttribute({$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}TypInfo.GetAttribute(at, i));
  3829. end;
  3830. FAttributesResolved:=true;
  3831. end;
  3832. result := FAttributes;
  3833. end;
  3834. function TRttiProperty.GetValue(Instance: pointer): TValue;
  3835. procedure ValueFromBool(value: Int64);
  3836. var
  3837. b8: Boolean;
  3838. b16: Boolean16;
  3839. b32: Boolean32;
  3840. bb: ByteBool;
  3841. bw: WordBool;
  3842. bl: LongBool;
  3843. td: PTypeData;
  3844. p: Pointer;
  3845. begin
  3846. td := GetTypeData(FPropInfo^.PropType);
  3847. case td^.OrdType of
  3848. otUByte:
  3849. begin
  3850. b8 := Boolean(value);
  3851. p := @b8;
  3852. end;
  3853. otUWord:
  3854. begin
  3855. b16 := Boolean16(value);
  3856. p := @b16;
  3857. end;
  3858. otULong:
  3859. begin
  3860. b32 := Boolean32(value);
  3861. p := @b32;
  3862. end;
  3863. otSByte:
  3864. begin
  3865. bb := ByteBool(value);
  3866. p := @bb;
  3867. end;
  3868. otSWord:
  3869. begin
  3870. bw := WordBool(value);
  3871. p := @bw;
  3872. end;
  3873. otSLong:
  3874. begin
  3875. bl := LongBool(value);
  3876. p := @bl;
  3877. end;
  3878. end;
  3879. TValue.Make(p, FPropInfo^.PropType, result);
  3880. end;
  3881. procedure ValueFromInt(value: Int64);
  3882. var
  3883. i8: UInt8;
  3884. i16: UInt16;
  3885. i32: UInt32;
  3886. td: PTypeData;
  3887. p: Pointer;
  3888. begin
  3889. td := GetTypeData(FPropInfo^.PropType);
  3890. case td^.OrdType of
  3891. otUByte,
  3892. otSByte:
  3893. begin
  3894. i8 := value;
  3895. p := @i8;
  3896. end;
  3897. otUWord,
  3898. otSWord:
  3899. begin
  3900. i16 := value;
  3901. p := @i16;
  3902. end;
  3903. otULong,
  3904. otSLong:
  3905. begin
  3906. i32 := value;
  3907. p := @i32;
  3908. end;
  3909. end;
  3910. TValue.Make(p, FPropInfo^.PropType, result);
  3911. end;
  3912. var
  3913. Values: record
  3914. case Integer of
  3915. 0: (Enum: Int64);
  3916. 1: (Bool: Int64);
  3917. 2: (Int: Int64);
  3918. 3: (Ch: Byte);
  3919. 4: (Wch: Word);
  3920. 5: (I64: Int64);
  3921. 6: (Si: Single);
  3922. 7: (Db: Double);
  3923. 8: (Ex: Extended);
  3924. 9: (Cur: Currency);
  3925. 10: (Cp: Comp);
  3926. 11: (A: Pointer;)
  3927. end;
  3928. s: String;
  3929. ss: ShortString;
  3930. u : UnicodeString;
  3931. O: TObject;
  3932. Int: IUnknown;
  3933. begin
  3934. case FPropinfo^.PropType^.Kind of
  3935. tkSString:
  3936. begin
  3937. ss := ShortString(GetStrProp(TObject(Instance), FPropInfo));
  3938. TValue.Make(@ss, FPropInfo^.PropType, result);
  3939. end;
  3940. tkAString:
  3941. begin
  3942. s := GetStrProp(TObject(Instance), FPropInfo);
  3943. TValue.Make(@s, FPropInfo^.PropType, result);
  3944. end;
  3945. tkUString:
  3946. begin
  3947. U := GetUnicodeStrProp(TObject(Instance), FPropInfo);
  3948. TValue.Make(@U, FPropInfo^.PropType, result);
  3949. end;
  3950. tkWString:
  3951. begin
  3952. U := GetWideStrProp(TObject(Instance), FPropInfo);
  3953. TValue.Make(@U, FPropInfo^.PropType, result);
  3954. end;
  3955. tkEnumeration:
  3956. begin
  3957. Values.Enum := Integer(GetOrdProp(TObject(Instance), FPropInfo));
  3958. ValueFromInt(Values.Enum);
  3959. end;
  3960. tkBool:
  3961. begin
  3962. Values.Bool := GetOrdProp(TObject(Instance), FPropInfo);
  3963. ValueFromBool(Values.Bool);
  3964. end;
  3965. tkInteger:
  3966. begin
  3967. Values.Int := GetOrdProp(TObject(Instance), FPropInfo);
  3968. ValueFromInt(Values.Int);
  3969. end;
  3970. tkChar:
  3971. begin
  3972. Values.Ch := Byte(GetOrdProp(TObject(Instance), FPropInfo));
  3973. TValue.Make(@Values.Ch, FPropInfo^.PropType, result);
  3974. end;
  3975. tkWChar:
  3976. begin
  3977. Values.Wch := Word(GetOrdProp(TObject(Instance), FPropInfo));
  3978. TValue.Make(@Values.Wch, FPropInfo^.PropType, result);
  3979. end;
  3980. tkInt64,
  3981. tkQWord:
  3982. begin
  3983. Values.I64 := GetOrdProp(TObject(Instance), FPropInfo);
  3984. TValue.Make(@Values.I64, FPropInfo^.PropType, result);
  3985. end;
  3986. tkClass:
  3987. begin
  3988. O := GetObjectProp(TObject(Instance), FPropInfo);
  3989. TValue.Make(@O, FPropInfo^.PropType, Result);
  3990. end;
  3991. tkInterface:
  3992. begin
  3993. Int := GetInterfaceProp(TObject(Instance), FPropInfo);
  3994. TValue.Make(@Int, FPropInfo^.PropType, Result);
  3995. end;
  3996. tkFloat:
  3997. begin
  3998. case GetTypeData(FPropInfo^.PropType)^.FloatType of
  3999. ftCurr :
  4000. begin
  4001. Values.Cur := Currency(GetFloatProp(TObject(Instance), FPropInfo));
  4002. TValue.Make(@Values.Cur, FPropInfo^.PropType, Result);
  4003. end;
  4004. ftSingle :
  4005. begin
  4006. Values.Si := Single(GetFloatProp(TObject(Instance), FPropInfo));
  4007. TValue.Make(@Values.Si, FPropInfo^.PropType, Result);
  4008. end;
  4009. ftDouble :
  4010. begin
  4011. Values.Db := Double(GetFloatProp(TObject(Instance), FPropInfo));
  4012. TValue.Make(@Values.Db, FPropInfo^.PropType, Result);
  4013. end;
  4014. ftExtended:
  4015. begin
  4016. Values.Ex := GetFloatProp(TObject(Instance), FPropInfo);
  4017. TValue.Make(@Values.Ex, FPropInfo^.PropType, Result);
  4018. end;
  4019. ftComp :
  4020. begin
  4021. Values.Cp := Comp(GetFloatProp(TObject(Instance), FPropInfo));
  4022. TValue.Make(@Values.Cp, FPropInfo^.PropType, Result);
  4023. end;
  4024. end;
  4025. end;
  4026. tkDynArray:
  4027. begin
  4028. Values.A := GetDynArrayProp(TObject(Instance), FPropInfo);
  4029. TValue.Make(@Values.A, FPropInfo^.PropType, Result);
  4030. end
  4031. else
  4032. result := TValue.Empty;
  4033. end
  4034. end;
  4035. procedure TRttiProperty.SetValue(Instance: pointer; const AValue: TValue);
  4036. begin
  4037. case FPropinfo^.PropType^.Kind of
  4038. tkSString,
  4039. tkAString:
  4040. SetStrProp(TObject(Instance), FPropInfo, AValue.AsString);
  4041. tkUString:
  4042. SetUnicodeStrProp(TObject(Instance), FPropInfo, AValue.AsUnicodeString);
  4043. tkWString:
  4044. SetWideStrProp(TObject(Instance), FPropInfo, AValue.AsUnicodeString);
  4045. tkInteger,
  4046. tkInt64,
  4047. tkQWord,
  4048. tkChar,
  4049. tkBool,
  4050. tkWChar,
  4051. tkEnumeration:
  4052. SetOrdProp(TObject(Instance), FPropInfo, AValue.AsOrdinal);
  4053. tkClass:
  4054. SetObjectProp(TObject(Instance), FPropInfo, AValue.AsObject);
  4055. tkInterface:
  4056. SetInterfaceProp(TObject(Instance), FPropInfo, AValue.AsInterface);
  4057. tkFloat:
  4058. SetFloatProp(TObject(Instance), FPropInfo, AValue.AsExtended);
  4059. tkDynArray:
  4060. SetDynArrayProp(TObject(Instance), FPropInfo, PPointer(AValue.GetReferenceToRawData)^);
  4061. else
  4062. raise exception.createFmt(SErrUnableToSetValueForType, [PropertyType.Name]);
  4063. end
  4064. end;
  4065. function TRttiType.GetIsInstance: boolean;
  4066. begin
  4067. result := false;
  4068. end;
  4069. function TRttiType.GetIsManaged: boolean;
  4070. begin
  4071. result := {$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}Rtti.IsManaged(FTypeInfo);
  4072. end;
  4073. function TRttiType.GetIsOrdinal: boolean;
  4074. begin
  4075. result := false;
  4076. end;
  4077. function TRttiType.GetIsRecord: boolean;
  4078. begin
  4079. result := false;
  4080. end;
  4081. function TRttiType.GetIsSet: boolean;
  4082. begin
  4083. result := false;
  4084. end;
  4085. function TRttiType.GetAsInstance: TRttiInstanceType;
  4086. begin
  4087. // This is a ridicoulous design, but Delphi-compatible...
  4088. result := TRttiInstanceType(self);
  4089. end;
  4090. function TRttiType.GetBaseType: TRttiType;
  4091. begin
  4092. result := nil;
  4093. end;
  4094. function TRttiType.GetTypeKind: TTypeKind;
  4095. begin
  4096. result := FTypeInfo^.Kind;
  4097. end;
  4098. function TRttiType.GetTypeSize: integer;
  4099. begin
  4100. result := -1;
  4101. end;
  4102. function TRttiType.GetName: string;
  4103. begin
  4104. Result:=FTypeInfo^.Name;
  4105. end;
  4106. function TRttiType.GetHandle: Pointer;
  4107. begin
  4108. Result := FTypeInfo;
  4109. end;
  4110. constructor TRttiType.Create(ATypeInfo: PTypeInfo);
  4111. begin
  4112. inherited Create();
  4113. FTypeInfo:=ATypeInfo;
  4114. if assigned(FTypeInfo) then
  4115. FTypeData:=GetTypeData(ATypeInfo);
  4116. end;
  4117. destructor TRttiType.Destroy;
  4118. var
  4119. attr: TCustomAttribute;
  4120. begin
  4121. for attr in FAttributes do
  4122. attr.Free;
  4123. inherited;
  4124. end;
  4125. function TRttiType.GetAttributes: TCustomAttributeArray;
  4126. var
  4127. i: Integer;
  4128. at: PAttributeTable;
  4129. begin
  4130. if not FAttributesResolved then
  4131. begin
  4132. at := GetAttributeTable(FTypeInfo);
  4133. if Assigned(at) then
  4134. begin
  4135. setlength(FAttributes,at^.AttributeCount);
  4136. for i := 0 to at^.AttributeCount-1 do
  4137. FAttributes[i]:={$IFDEF FPC_DOTTEDUNITS}System.{$ENDIF}TypInfo.GetAttribute(at,i);
  4138. end;
  4139. FAttributesResolved:=true;
  4140. end;
  4141. result := FAttributes;
  4142. end;
  4143. function TRttiType.GetProperties: specialize TArray<TRttiProperty>;
  4144. begin
  4145. Result := Nil;
  4146. end;
  4147. function TRttiType.GetProperty(const AName: string): TRttiProperty;
  4148. var
  4149. FPropList: specialize TArray<TRttiProperty>;
  4150. i: Integer;
  4151. begin
  4152. result := nil;
  4153. FPropList := GetProperties;
  4154. for i := 0 to length(FPropList)-1 do
  4155. if sametext(FPropList[i].Name,AName) then
  4156. begin
  4157. result := FPropList[i];
  4158. break;
  4159. end;
  4160. end;
  4161. function TRttiType.GetMethods: specialize TArray<TRttiMethod>;
  4162. var
  4163. parentmethods, selfmethods: specialize TArray<TRttiMethod>;
  4164. parent: TRttiType;
  4165. begin
  4166. if Assigned(fMethods) then
  4167. Exit(fMethods);
  4168. selfmethods := GetDeclaredMethods;
  4169. parent := GetBaseType;
  4170. if Assigned(parent) then begin
  4171. parentmethods := parent.GetMethods;
  4172. end;
  4173. fMethods := Concat(parentmethods, selfmethods);
  4174. Result := fMethods;
  4175. end;
  4176. function TRttiType.GetMethod(const aName: String): TRttiMethod;
  4177. var
  4178. methods: specialize TArray<TRttiMethod>;
  4179. method: TRttiMethod;
  4180. begin
  4181. methods := GetMethods;
  4182. for method in methods do
  4183. if SameText(method.Name, AName) then
  4184. Exit(method);
  4185. Result := Nil;
  4186. end;
  4187. function TRttiType.GetDeclaredMethods: specialize TArray<TRttiMethod>;
  4188. begin
  4189. Result := Nil;
  4190. end;
  4191. { TRttiNamedObject }
  4192. function TRttiNamedObject.GetName: string;
  4193. begin
  4194. result := '';
  4195. end;
  4196. function TRttiNamedObject.HasName(const aName: string): Boolean;
  4197. begin
  4198. Result:=SameText(Name,AName);
  4199. end;
  4200. { TRttiContext }
  4201. class function TRttiContext.Create: TRttiContext;
  4202. begin
  4203. result.FContextToken := nil;
  4204. end;
  4205. procedure TRttiContext.Free;
  4206. begin
  4207. FContextToken := nil;
  4208. end;
  4209. function TRttiContext.GetByHandle(AHandle: Pointer): TRttiObject;
  4210. begin
  4211. if not Assigned(FContextToken) then
  4212. FContextToken := TPoolToken.Create;
  4213. Result := (FContextToken as IPooltoken).RttiPool.GetByHandle(AHandle);
  4214. end;
  4215. procedure TRttiContext.AddObject(AObject: TRttiObject);
  4216. begin
  4217. if not Assigned(FContextToken) then
  4218. FContextToken := TPoolToken.Create;
  4219. (FContextToken as IPooltoken).RttiPool.AddObject(AObject);
  4220. end;
  4221. function TRttiContext.GetType(ATypeInfo: PTypeInfo): TRttiType;
  4222. begin
  4223. if not assigned(FContextToken) then
  4224. FContextToken := TPoolToken.Create;
  4225. result := (FContextToken as IPooltoken).RttiPool.GetType(ATypeInfo);
  4226. end;
  4227. function TRttiContext.GetType(AClass: TClass): TRttiType;
  4228. begin
  4229. if assigned(AClass) then
  4230. result := GetType(PTypeInfo(AClass.ClassInfo))
  4231. else
  4232. result := nil;
  4233. end;
  4234. {function TRttiContext.GetTypes: specialize TArray<TRttiType>;
  4235. begin
  4236. if not assigned(FContextToken) then
  4237. FContextToken := TPoolToken.Create;
  4238. result := (FContextToken as IPooltoken).RttiPool.GetTypes;
  4239. end;}
  4240. { TVirtualInterface }
  4241. {.$define DEBUG_VIRTINTF}
  4242. constructor TVirtualInterface.Create(aPIID: PTypeInfo);
  4243. const
  4244. BytesToPopQueryInterface =
  4245. {$ifdef cpui386}
  4246. 3 * SizeOf(Pointer); { aIID + aObj + $RetAddr }
  4247. {$else}
  4248. 0;
  4249. {$endif}
  4250. BytesToPopAddRef =
  4251. {$ifdef cpui386}
  4252. 1 * SizeOf(Pointer); { $RetAddr }
  4253. {$else}
  4254. 0;
  4255. {$endif}
  4256. BytesToPopRelease =
  4257. {$ifdef cpui386}
  4258. 1 * SizeOf(Pointer); { $RetAddr }
  4259. {$else}
  4260. 0;
  4261. {$endif}
  4262. var
  4263. t: TRttiType;
  4264. ti: PTypeInfo;
  4265. td: PInterfaceData;
  4266. methods: specialize TArray<TRttiMethod>;
  4267. m: TRttiMethod;
  4268. mt: PIntfMethodTable;
  4269. count, i: SizeInt;
  4270. begin
  4271. if not Assigned(aPIID) then
  4272. raise EArgumentNilException.Create(SErrVirtIntfTypeNil);
  4273. { ToDo: add support for raw interfaces once they support RTTI }
  4274. if aPIID^.Kind <> tkInterface then
  4275. raise EArgumentException.CreateFmt(SErrVirtIntfTypeMustBeIntf, [aPIID^.Name]);
  4276. fContext := TRttiContext.Create;
  4277. t := fContext.GetType(aPIID);
  4278. if not Assigned(t) then
  4279. raise EInsufficientRtti.CreateFmt(SErrVirtIntfTypeNotFound, [aPIID^.Name]);
  4280. { check whether the interface and all its parents have RTTI enabled (the only
  4281. exception is IInterface as we know the methods of that) }
  4282. td := PInterfaceData(GetTypeData(aPIID));
  4283. fGUID := td^.GUID;
  4284. fThunks[0] := AllocateRawThunk(TMethod(@QueryInterface).Code, Pointer(Self), BytesToPopQueryInterface);
  4285. fThunks[1] := AllocateRawThunk(TMethod(@_AddRef).Code, Pointer(Self), BytesToPopAddRef);
  4286. fThunks[2] := AllocateRawThunk(TMethod(@_Release).Code, Pointer(Self), BytesToPopRelease);
  4287. for i := Low(fThunks) to High(fThunks) do
  4288. if not Assigned(fThunks[i]) then
  4289. raise ENotImplemented.CreateFmt(SErrVirtIntfCreateThunk, [aPIID^.Name]);
  4290. ti := aPIID;
  4291. { ignore the three methods of IInterface }
  4292. count := 0;
  4293. while ti <> TypeInfo(IInterface) do begin
  4294. mt := td^.MethodTable;
  4295. if (mt^.Count > 0) and (mt^.RTTICount <> mt^.Count) then
  4296. raise EInsufficientRtti.CreateFmt(SErrVirtIntfNotAllMethodsRTTI, [aPIID^.Name]);
  4297. Inc(count, mt^.Count);
  4298. ti := td^.Parent^;
  4299. td := PInterfaceData(GetTypeData(ti));
  4300. end;
  4301. SetLength(fImpls, count);
  4302. methods := t.GetMethods;
  4303. for m in methods do begin
  4304. if m.VirtualIndex > High(fImpls) + Length(fThunks) then
  4305. raise ERtti.CreateFmt(SErrVirtIntfInvalidVirtIdx, [aPIID^.Name, m.Name, m.VirtualIndex]);
  4306. if m.VirtualIndex < Length(fThunks) then
  4307. raise ERtti.CreateFmt(SErrVirtIntfInvalidVirtIdx, [aPIID^.Name, m.Name, m.VirtualIndex]);
  4308. { we use the childmost entry, except for the IInterface methods }
  4309. if Assigned(fImpls[m.VirtualIndex - Length(fThunks)]) then begin
  4310. {$IFDEF DEBUG_VIRTINTF}Writeln('Ignoring duplicate implementation for index ', m.VirtualIndex);{$ENDIF}
  4311. Continue;
  4312. end;
  4313. fImpls[m.VirtualIndex - Length(fThunks)] := m.CreateImplementation(m, @HandleUserCallback);
  4314. end;
  4315. for i := 0 to High(fImpls) do
  4316. if not Assigned(fImpls) then
  4317. raise ERtti.CreateFmt(SErrVirtIntfMethodNil, [aPIID^.Name, i]);
  4318. fVmt := GetMem(Length(fImpls) * SizeOf(CodePointer) + Length(fThunks) * SizeOf(CodePointer));
  4319. if not Assigned(fVmt) then
  4320. raise ERtti.CreateFmt(SErrVirtIntfCreateVmt, [aPIID^.Name]);
  4321. for i := 0 to High(fThunks) do begin
  4322. fVmt[i] := fThunks[i];
  4323. {$IFDEF DEBUG_VIRTINTF}Writeln('VMT ', i, ': ', HexStr(fVmt[i]));{$ENDIF}
  4324. end;
  4325. for i := 0 to High(fImpls) do begin
  4326. fVmt[i + Length(fThunks)] := fImpls[i].CodeAddress;
  4327. {$IFDEF DEBUG_VIRTINTF}Writeln('VMT ', i + Length(fThunks), ': ', HexStr(fVmt[i + Length(fThunks)]));{$ENDIF}
  4328. end;
  4329. end;
  4330. constructor TVirtualInterface.Create(aPIID: PTypeInfo; aInvokeEvent: TVirtualInterfaceInvokeEvent);
  4331. begin
  4332. Create(aPIID);
  4333. OnInvoke := aInvokeEvent;
  4334. end;
  4335. destructor TVirtualInterface.Destroy;
  4336. var
  4337. impl: TMethodImplementation;
  4338. thunk: CodePointer;
  4339. begin
  4340. {$IFDEF DEBUG_VIRTINTF}Writeln('Freeing implementations');{$ENDIF}
  4341. for impl in fImpls do
  4342. impl.Free;
  4343. {$IFDEF DEBUG_VIRTINTF}Writeln('Freeing thunks');{$ENDIF}
  4344. for thunk in fThunks do
  4345. FreeRawThunk(thunk);
  4346. {$IFDEF DEBUG_VIRTINTF}Writeln('Freeing VMT');{$ENDIF}
  4347. if Assigned(fVmt) then
  4348. FreeMem(fVmt);
  4349. {$IFDEF DEBUG_VIRTINTF}Writeln('Freeing Context');{$ENDIF}
  4350. fContext.Free;
  4351. {$IFDEF DEBUG_VIRTINTF}Writeln('Done');{$ENDIF}
  4352. inherited Destroy;
  4353. end;
  4354. function TVirtualInterface.QueryInterface(constref aIID: TGuid; out aObj): LongInt;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
  4355. begin
  4356. {$IFDEF DEBUG_VIRTINTF}Writeln('QueryInterface for ', GUIDToString(aIID));{$ENDIF}
  4357. if IsEqualGUID(aIID, fGUID) then begin
  4358. {$IFDEF DEBUG_VIRTINTF}Writeln('Returning ', HexStr(@fVmt));{$ENDIF}
  4359. Pointer(aObj) := @fVmt;
  4360. { QueryInterface increases the reference count }
  4361. _AddRef;
  4362. Result := S_OK;
  4363. end else
  4364. Result := inherited QueryInterface(aIID, aObj);
  4365. end;
  4366. procedure TVirtualInterface.HandleUserCallback(aUserData: Pointer; const aArgs: TValueArray; out aResult: TValue);
  4367. begin
  4368. {$IFDEF DEBUG_VIRTINTF}Writeln('Call for ', TRttiMethod(aUserData).Name);{$ENDIF}
  4369. if Assigned(fOnInvoke) then
  4370. fOnInvoke(TRttiMethod(aUserData), aArgs, aResult);
  4371. end;
  4372. function TRttiObject.GetAttribute(aClass: TCustomAttributeClass): TCustomAttribute;
  4373. var
  4374. attrarray : TCustomAttributeArray;
  4375. a: TCustomAttribute;
  4376. begin
  4377. Result:=nil;
  4378. attrarray:=GetAttributes;
  4379. for a in attrarray do
  4380. if a.InheritsFrom(aClass) then
  4381. Exit(a);
  4382. end;
  4383. function TRttiObject.HasAttribute(aClass: TCustomAttributeClass): Boolean;
  4384. begin
  4385. Result:=Assigned(GetAttribute(aClass));
  4386. end;
  4387. generic function TRttiObject.GetAttribute<T>: T;
  4388. begin
  4389. Result:=T(GetAttribute(T));
  4390. end;
  4391. generic function TRttiObject.HasAttribute<T>: Boolean;
  4392. begin
  4393. Result:=HasAttribute(T);
  4394. end;
  4395. {$ifndef InLazIDE}
  4396. {$if defined(CPUI386) or (defined(CPUX86_64) and defined(WIN64))}
  4397. {$I invoke.inc}
  4398. {$endif}
  4399. {$endif}
  4400. initialization
  4401. PoolRefCount := 0;
  4402. InitDefaultFunctionCallManager;
  4403. {$ifdef SYSTEM_HAS_INVOKE}
  4404. InitSystemFunctionCallManager;
  4405. {$endif}
  4406. end.