writer.pas 99 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109
  1. {
  2. pas2jni - JNI bridge generator for Pascal.
  3. Copyright (c) 2013 by Yury Sidorov.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  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. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************}
  16. unit writer;
  17. {$mode objfpc}{$H+}
  18. interface
  19. //{$define DEBUG}
  20. {$ifdef DEBUG}
  21. {$ASSERTIONS ON}
  22. {$endif}
  23. uses
  24. Classes, SysUtils, def, contnrs, PPUParser;
  25. const
  26. MaxMethodPointers = 10000;
  27. type
  28. { TTextOutStream }
  29. TTextOutStream = class(TFileStream)
  30. private
  31. FIndent: integer;
  32. FIndStr: string;
  33. procedure SetIndednt(const AValue: integer);
  34. public
  35. procedure Write(const s: ansistring); overload;
  36. procedure WriteLn(const s: ansistring = ''; ExtraIndent: integer = 0);
  37. procedure IncI;
  38. procedure DecI;
  39. property Indent: integer read FIndent write SetIndednt;
  40. property SIndent: string read FIndStr;
  41. end;
  42. { TClassInfo }
  43. TClassInfo = class
  44. public
  45. Def: TDef;
  46. Funcs: TObjectList;
  47. IsCommonClass: boolean;
  48. constructor Create;
  49. destructor Destroy; override;
  50. end;
  51. { TProcInfo }
  52. TProcInfo = class
  53. public
  54. Name: string;
  55. JniName: string;
  56. JniSignature: string;
  57. end;
  58. { TClassList }
  59. TClassList = class(TStringList)
  60. private
  61. function GetFullName(const AName: string; Def: TDef): string;
  62. public
  63. constructor Create;
  64. function Add(const AName: string; Def: TDef; Info: TClassInfo): integer;
  65. function IndexOf(const AName: string; Def: TDef): integer; reintroduce;
  66. function GetClassName(Index: integer): string;
  67. function GetClassInfo(Index: integer): TClassInfo;
  68. end;
  69. { TWriter }
  70. TWriter = class
  71. private
  72. Fjs, Fps: TTextOutStream;
  73. FClasses: TClassList;
  74. FPkgDir: string;
  75. FUniqueCnt: integer;
  76. FThisUnit: TUnitDef;
  77. FIntegerType: TDef;
  78. FRecords: TObjectList;
  79. FRealClasses: TObjectList;
  80. function DoCheckItem(const ItemName: string): TCheckItemResult;
  81. procedure WriteClassTable;
  82. procedure WriteFileComment(st: TTextOutStream);
  83. function FindInStringList(list: TStringList; const s: string): integer;
  84. procedure ProcessRules(d: TDef; const Prefix: string = '');
  85. function GetUniqueNum: integer;
  86. function DefToJniType(d: TDef; var err: boolean): string;
  87. function DefToJniSig(d: TDef): string;
  88. function DefToJavaType(d: TDef): string;
  89. function GetJavaClassPath(d: TDef; const AClassName: string = ''): string;
  90. function JniToPasType(d: TDef; const v: string; CheckNil: boolean): string;
  91. function PasToJniType(d: TDef; const v: string): string;
  92. function GetTypeInfoVar(ClassDef: TDef): string;
  93. function GetClassPrefix(ClassDef: TDef; const AClassName: string = ''): string;
  94. function IsJavaSimpleType(d: TDef): boolean;
  95. function IsJavaVarParam(ParamDef: TVarDef): boolean;
  96. function GetProcDeclaration(d: TProcDef; const ProcName: string = ''; FullTypeNames: boolean = False; InternalParaNames: boolean = False): string;
  97. function GetJavaProcDeclaration(d: TProcDef; const ProcName: string = ''): string;
  98. function GetJniFuncType(d: TDef): string;
  99. function GetJavaClassName(cls: TDef; it: TDef): string;
  100. procedure RegisterPseudoClass(d: TDef);
  101. function GetPasIntType(Size: integer): string;
  102. function GetPasType(d: TDef; FullName: boolean): string;
  103. // procedure AddCustomProc(ParentDef: TDef; const JniName, Name: string; RetType: TBasicType; const Params: array of TBasicType);
  104. function AddCustomProc(ParentDef: TDef; const JniName, Name: string; RetType: TBasicType; const Params: array of TBasicType): TProcDef;
  105. procedure AddNativeMethod(ParentDef: TDef; const JniName, Name, Signature: string);
  106. function GetProcSignature(d: TProcDef): string;
  107. procedure EHandlerStart;
  108. procedure EHandlerEnd(const EnvVarName: string; const ExtraCode: string = '');
  109. procedure UpdateUsedUnits(u: TUnitDef);
  110. procedure WriteClassInfoVar(d: TDef);
  111. procedure WriteComment(d: TDef; const AType: string);
  112. procedure WriteClass(d: TClassDef; PreInfo: boolean);
  113. procedure WriteProc(d: TProcDef; Variable: TVarDef = nil; AParent: TDef = nil);
  114. procedure WriteVar(d: TVarDef; AParent: TDef = nil);
  115. procedure WriteConst(d: TConstDef);
  116. procedure WriteEnum(d: TDef);
  117. procedure WriteProcType(d: TProcDef; PreInfo: boolean);
  118. procedure WriteSet(d: TSetDef);
  119. procedure WritePointer(d: TPointerDef; PreInfo: boolean);
  120. procedure WriteClassRef(d: TClassRefDef; PreInfo: boolean);
  121. procedure WriteUnit(u: TUnitDef);
  122. procedure WriteOnLoad;
  123. procedure WriteRecordSizes;
  124. public
  125. SearchPath: string;
  126. LibName: string;
  127. JavaPackage: string;
  128. Units: TStringList;
  129. OutPath: string;
  130. JavaOutPath: string;
  131. IncludeList: TStringList;
  132. ExcludeList: TStringList;
  133. LibAutoLoad: boolean;
  134. constructor Create;
  135. destructor Destroy; override;
  136. procedure ProcessUnits;
  137. end;
  138. implementation
  139. const
  140. JNIType: array[TBasicType] of string =
  141. ('', 'jshort', 'jbyte', 'jint', 'jshort', 'jlong', 'jint', 'jlong', 'jfloat', 'jdouble', 'jstring',
  142. 'jstring', 'jboolean', 'jchar', 'jchar', 'jint', 'jstring');
  143. JNITypeSig: array[TBasicType] of string =
  144. ('V', 'S', 'B', 'I', 'S', 'J', 'I', 'J', 'F', 'D', 'Ljava/lang/String;', 'Ljava/lang/String;',
  145. 'Z', 'C', 'C', 'I', 'Ljava/lang/String;');
  146. JavaType: array[TBasicType] of string =
  147. ('void', 'short', 'byte', 'int', 'short', 'long', 'int', 'long', 'float', 'double', 'String',
  148. 'String', 'boolean', 'char', 'char', 'int', 'String');
  149. TextIndent = 2;
  150. ExcludeStd: array[1..44] of string = (
  151. 'classes.TStream.ReadComponent', 'classes.TStream.ReadComponentRes', 'classes.TStream.WriteComponent', 'classes.TStream.WriteComponentRes',
  152. 'classes.TStream.WriteDescendent', 'classes.TStream.WriteDescendentRes', 'classes.TStream.WriteResourceHeader', 'classes.TStream.FixupResourceHeader',
  153. 'classes.TStream.ReadResHeader', 'classes.TComponent.WriteState', 'classes.TComponent.ExecuteAction', 'classes.TComponent.UpdateAction',
  154. 'classes.TComponent.GetEnumerator', 'classes.TComponent.VCLComObject', 'classes.TComponent.DesignInfo', 'classes.TComponent.Destroying',
  155. 'classes.TComponent.FreeNotification', 'classes.TComponent.RemoveFreeNotification', 'classes.TComponent.FreeOnRelease', 'classes.TComponent.SetSubComponent',
  156. 'system.TObject.newinstance', 'system.TObject.FreeInstance', 'system.TObject.SafeCallException', 'system.TObject.InitInstance',
  157. 'system.TObject.CleanupInstance', 'system.TObject.ClassInfo', 'system.TObject.AfterConstruction', 'system.TObject.BeforeDestruction',
  158. 'system.TObject.GetInterfaceEntry', 'system.TObject.GetInterfaceTable', 'system.TObject.MethodAddress', 'system.TObject.MethodName',
  159. 'system.TObject.FieldAddress', 'classes.TComponent.ComponentState', 'classes.TComponent.ComponentStyle', 'classes.TList.GetEnumerator',
  160. 'classes.TList.List', 'classes.TList.FPOAttachObserver', 'classes.TList.FPODetachObserver', 'classes.TList.FPONotifyObservers',
  161. 'classes.TPersistent.FPOAttachObserver', 'classes.TPersistent.FPODetachObserver', 'classes.TPersistent.FPONotifyObservers',
  162. 'system.fma'
  163. );
  164. ExcludeDelphi7: array[1..26] of string = (
  165. 'system.TObject.StringMessageTable', 'system.TObject.GetInterfaceEntryByStr', 'system.TObject.UnitName', 'system.TObject.Equals',
  166. 'system.TObject.GetHashCode', 'system.TObject.ToString','system.TObject.QualifiedClassName','classes.TStream.ReadByte', 'classes.TStream.ReadWord',
  167. 'classes.TStream.ReadDWord', 'classes.TStream.ReadQWord', 'classes.TStream.ReadAnsiString', 'classes.TStream.WriteByte',
  168. 'classes.TStream.WriteWord', 'classes.TStream.WriteDWord', 'classes.TStream.WriteQWord', 'classes.TStream.WriteAnsiString',
  169. 'classes.TCollection.Exchange', 'classes.TStrings.Equals', 'classes.TStrings.GetNameValue', 'classes.TStrings.ExtractName',
  170. 'classes.TStrings.TextLineBreakStyle', 'classes.TStrings.StrictDelimiter', 'classes.TStrings.GetEnumerator', 'classes.TStringList.OwnsObjects',
  171. 'classes.TList.AddList'
  172. );
  173. SUnsupportedType = '<unsupported type>';
  174. function JniCaliing: string;
  175. begin
  176. Result:='{$ifdef mswindows} stdcall {$else} cdecl {$endif};';
  177. end;
  178. { TClassList }
  179. function TClassList.IndexOf(const AName: string; Def: TDef): integer;
  180. begin
  181. Result:=inherited IndexOf(GetFullName(AName, Def));
  182. end;
  183. function TClassList.GetClassName(Index: integer): string;
  184. var
  185. i: integer;
  186. begin
  187. Result:=Strings[Index];
  188. i:=Pos('.', Result);
  189. if i > 0 then
  190. System.Delete(Result, 1, i);
  191. end;
  192. function TClassList.GetClassInfo(Index: integer): TClassInfo;
  193. begin
  194. Result:=TClassInfo(Objects[Index]);
  195. end;
  196. function TClassList.GetFullName(const AName: string; Def: TDef): string;
  197. begin
  198. if (Def = nil) or (Def.DefType = dtUnit) then
  199. Result:=AName
  200. else begin
  201. while (Def.Parent <> nil) and (Def.DefType <> dtUnit) do
  202. Def:=Def.Parent;
  203. Result:=Def.Name + '.' + AName;
  204. end;
  205. end;
  206. constructor TClassList.Create;
  207. begin
  208. inherited Create;
  209. Sorted:=True;
  210. end;
  211. function TClassList.Add(const AName: string; Def: TDef; Info: TClassInfo): integer;
  212. begin
  213. Result:=AddObject(GetFullName(AName, Def), Info);
  214. end;
  215. { TTextOutStream }
  216. procedure TTextOutStream.SetIndednt(const AValue: integer);
  217. begin
  218. if FIndent = AValue then exit;
  219. FIndent:=AValue;
  220. SetLength(FIndStr, FIndent*TextIndent);
  221. if FIndent > 0 then
  222. FillChar(FIndStr[1], FIndent*TextIndent, ' ');
  223. end;
  224. procedure TTextOutStream.Write(const s: ansistring);
  225. begin
  226. WriteBuffer(PChar(s)^, Length(s));
  227. end;
  228. procedure TTextOutStream.WriteLn(const s: ansistring; ExtraIndent: integer);
  229. begin
  230. if s = '' then
  231. Write(LineEnding)
  232. else begin
  233. Indent:=Indent + ExtraIndent;
  234. try
  235. Write(FIndStr + s + LineEnding);
  236. finally
  237. Indent:=Indent - ExtraIndent;
  238. end;
  239. end;
  240. end;
  241. procedure TTextOutStream.IncI;
  242. begin
  243. Indent:=Indent + 1;
  244. end;
  245. procedure TTextOutStream.DecI;
  246. begin
  247. if Indent > 0 then
  248. Indent:=Indent - 1;
  249. end;
  250. { TClassInfo }
  251. constructor TClassInfo.Create;
  252. begin
  253. Funcs:=TObjectList.Create(True);
  254. end;
  255. destructor TClassInfo.Destroy;
  256. begin
  257. Funcs.Free;
  258. inherited Destroy;
  259. end;
  260. { TWriter }
  261. function TWriter.DefToJniType(d: TDef; var err: boolean): string;
  262. begin
  263. if d = nil then begin
  264. Result:=SUnsupportedType;
  265. err:=True;
  266. end
  267. else begin
  268. if not d.IsUsed then begin
  269. Result:='<excluded type> ' + d.Name;
  270. err:=True;
  271. end
  272. else
  273. case d.DefType of
  274. dtType:
  275. Result:=JNIType[TTypeDef(d).BasicType];
  276. dtClass, dtEnum, dtClassRef:
  277. Result:='jobject';
  278. dtProcType:
  279. if poMethodPtr in TProcDef(d).ProcOpt then
  280. Result:='jobject'
  281. else begin
  282. Result:=SUnsupportedType + ' ' + d.Name;
  283. err:=True;
  284. end;
  285. dtSet:
  286. if TSetDef(d).Size <= 4 then
  287. Result:='jobject'
  288. else begin
  289. Result:=SUnsupportedType + ' ' + d.Name;
  290. err:=True;
  291. end;
  292. dtPointer:
  293. if TPointerDef(d).IsObjPtr then
  294. Result:='jobject'
  295. else
  296. Result:='jlong';
  297. dtJniObject:
  298. Result:='jobject';
  299. else begin
  300. Result:=SUnsupportedType + ' ' + d.Name;
  301. err:=True;
  302. d.SetNotUsed;
  303. end;
  304. end;
  305. end;
  306. end;
  307. function TWriter.DoCheckItem(const ItemName: string): TCheckItemResult;
  308. begin
  309. if FindInStringList(ExcludeList, ItemName) >= 0 then
  310. Result:=crExclude
  311. else
  312. if FindInStringList(IncludeList, ItemName) >= 0 then
  313. Result:=crInclude
  314. else
  315. Result:=crDefault;
  316. end;
  317. procedure TWriter.WriteFileComment(st: TTextOutStream);
  318. begin
  319. st.WriteLn('// This file was automatically generated by the pas2jni utility.');
  320. st.WriteLn('// Do not edit this file.');
  321. end;
  322. function TWriter.FindInStringList(list: TStringList; const s: string): integer;
  323. var
  324. len, cnt: integer;
  325. ss: string;
  326. begin
  327. if list.Find(s, Result) or (Result < 0) then
  328. exit;
  329. if Result < list.Count then begin
  330. cnt:=3;
  331. if Result > 0 then
  332. Dec(Result)
  333. else
  334. Dec(cnt);
  335. if Result + cnt > list.Count then
  336. Dec(cnt);
  337. while cnt > 0 do begin
  338. ss:=list[Result];
  339. len:=Length(ss);
  340. if (len > 1) and (ss[len] = '*') then begin
  341. Dec(len);
  342. if AnsiCompareText(Copy(s, 1, len), Copy(ss, 1, len)) = 0 then
  343. exit;
  344. end;
  345. Inc(Result);
  346. Dec(cnt);
  347. end;
  348. end;
  349. Result:=-1;
  350. end;
  351. procedure TWriter.ProcessRules(d: TDef; const Prefix: string);
  352. var
  353. i: integer;
  354. s: string;
  355. begin
  356. if d.DefType = dtClass then
  357. with TClassDef(d) do
  358. if (AncestorClass = nil) and (CType in [ctClass, ctInterface]) and (CompareText(Parent.Name, 'system') <> 0) then begin
  359. SetNotUsed;
  360. exit;
  361. end;
  362. s:=Prefix + d.Name;
  363. if FindInStringList(ExcludeList, s) >= 0 then
  364. d.SetNotUsed
  365. else
  366. if FindInStringList(IncludeList, s) >= 0 then
  367. d.IsUsed:=True;
  368. if not (d.DefType in [dtUnit, dtClass]) then
  369. exit;
  370. s:=s + '.';
  371. for i:=0 to d.Count - 1 do
  372. ProcessRules(d[i], s);
  373. end;
  374. function TWriter.GetUniqueNum: integer;
  375. begin
  376. Inc(FUniqueCnt);
  377. Result:=FUniqueCnt;
  378. end;
  379. function TWriter.DefToJniSig(d: TDef): string;
  380. begin
  381. if d = nil then
  382. Result:=SUnsupportedType
  383. else
  384. case d.DefType of
  385. dtType:
  386. Result:=JNITypeSig[TTypeDef(d).BasicType];
  387. dtClass, dtProcType, dtSet, dtEnum, dtClassRef:
  388. Result:='L' + GetJavaClassPath(d) + ';';
  389. dtPointer:
  390. if TPointerDef(d).IsObjPtr then
  391. Result:='L' + GetJavaClassPath(d) + ';'
  392. else
  393. Result:='J';
  394. dtJniObject:
  395. Result:='Ljava/lang/Object;';
  396. else
  397. Result:=SUnsupportedType;
  398. end;
  399. end;
  400. function TWriter.DefToJavaType(d: TDef): string;
  401. begin
  402. if d = nil then
  403. Result:=SUnsupportedType
  404. else
  405. if not d.IsUsed and (d.DefType <> dtType) then
  406. Result:='<excluded type> ' + d.Name
  407. else
  408. case d.DefType of
  409. dtType:
  410. Result:=JavaType[TTypeDef(d).BasicType];
  411. dtClass, dtProcType, dtSet, dtEnum, dtClassRef:
  412. Result:=d.Name;
  413. dtPointer:
  414. if TPointerDef(d).IsObjPtr then
  415. Result:=d.Name
  416. else
  417. Result:='long';
  418. dtJniObject:
  419. Result:='Object';
  420. else
  421. Result:=SUnsupportedType;
  422. end;
  423. end;
  424. function TWriter.GetJavaClassPath(d: TDef; const AClassName: string): string;
  425. var
  426. n: string;
  427. begin
  428. if AClassName = '' then
  429. n:=d.AliasName
  430. else
  431. n:=AClassName;
  432. Result:=StringReplace(JavaPackage, '.', '/', [rfReplaceAll]);
  433. if Result <> '' then
  434. Result:=Result + '/';
  435. if d.DefType = dtUnit then
  436. Result:=Result + n
  437. else
  438. Result:=Result + d.Parent.AliasName + '$' + n;
  439. end;
  440. procedure TWriter.WriteClass(d: TClassDef; PreInfo: boolean);
  441. var
  442. WrittenItems: TList;
  443. procedure _WriteConstructors(c: TClassDef; Written: TStringList);
  444. var
  445. i, j: integer;
  446. p: TProcDef;
  447. OldRet: TDef;
  448. s: string;
  449. begin
  450. if c = nil then
  451. exit;
  452. for i:=0 to c.Count - 1 do
  453. with c[i] do begin
  454. if (DefType = dtProc) and not c.IsPrivate and (TProcDef(c[i]).ProcType = ptConstructor) then begin
  455. p:=TProcDef(c[i]);
  456. j:=Written.IndexOf(p.Name);
  457. if (j < 0) or (Written.Objects[j] = c) then begin
  458. s:=p.Name + ':';
  459. for j:=0 to p.Count - 1 do
  460. if p[j].DefType = dtParam then
  461. s:=s + DefToJniSig(TVarDef(p[j]).VarType);
  462. if Written.IndexOf(s) < 0 then begin
  463. OldRet:=p.ReturnType;
  464. p.ReturnType:=d;
  465. p.Parent:=d;
  466. try
  467. WriteProc(p);
  468. finally
  469. p.ReturnType:=OldRet;
  470. p.Parent:=c;
  471. end;
  472. Written.Add(s);
  473. if not (poOverload in p.ProcOpt) then
  474. Written.AddObject(p.Name, c);
  475. end;
  476. end;
  477. end;
  478. end;
  479. _WriteConstructors(c.AncestorClass, Written);
  480. end;
  481. procedure WriteConstructors;
  482. var
  483. cc: TStringList;
  484. i: integer;
  485. begin
  486. if not TClassDef(d).HasAbstractMethods then begin
  487. // Writing all constructors including parent's
  488. cc:=TStringList.Create;
  489. try
  490. cc.Sorted:=True;
  491. _WriteConstructors(TClassDef(d), cc);
  492. finally
  493. cc.Free;
  494. end;
  495. end;
  496. if d.CType = ctClass then begin
  497. i:=FRealClasses.Add(d);
  498. Fjs.WriteLn(Format('public static %s Class() { return new %0:s(system.GetClassRef(%d)); }', [d.AliasName, i]));
  499. Fjs.WriteLn(Format('public static system.TClass TClass() { return system.GetTClass(%d); }', [i]));
  500. end;
  501. end;
  502. procedure _WriteReplacedItems(c: TClassDef);
  503. var
  504. i: integer;
  505. p: TReplDef;
  506. begin
  507. c:=c.AncestorClass;
  508. if c = nil then
  509. exit;
  510. if c.HasReplacedItems then begin
  511. for i:=0 to c.Count - 1 do
  512. with c[i] do begin
  513. p:=TReplDef(c[i]);
  514. if (DefType in ReplDefs) and ((p.IsReplaced) or p.IsReplImpl) then begin
  515. if p.ReplacedItem <> nil then
  516. WrittenItems.Add(p.ReplacedItem);
  517. if WrittenItems.IndexOf(p) >= 0 then
  518. continue;
  519. case p.DefType of
  520. dtProc:
  521. WriteProc(TProcDef(p), nil, d);
  522. dtProp, dtField:
  523. WriteVar(TVarDef(p), d);
  524. end;
  525. end;
  526. end;
  527. end;
  528. _WriteReplacedItems(c);
  529. end;
  530. procedure WriteReplacedItems;
  531. begin
  532. _WriteReplacedItems(TClassDef(d));
  533. end;
  534. procedure WriteItems(Regular, Replaced, ReplImpl: boolean);
  535. var
  536. i: integer;
  537. it: TReplDef;
  538. begin
  539. for i:=0 to d.Count - 1 do begin
  540. it:=TReplDef(d[i]);
  541. if not (it.DefType in ReplDefs) then
  542. continue;
  543. if not (it.IsReplImpl or it.IsReplaced) then begin
  544. if not Regular then
  545. continue;
  546. end
  547. else
  548. if (not Replaced and it.IsReplaced) or (not ReplImpl and it.IsReplImpl) then
  549. continue;
  550. if it.ReplacedItem <> nil then
  551. WrittenItems.Add(it.ReplacedItem);
  552. case it.DefType of
  553. dtProc:
  554. if TProcDef(it).ProcType <> ptConstructor then
  555. WriteProc(TProcDef(it));
  556. dtProp, dtField:
  557. WriteVar(TVarDef(it));
  558. end;
  559. end;
  560. end;
  561. procedure WriteTypeCast(const AName: string; SecondPass: boolean);
  562. var
  563. s, ss: string;
  564. begin
  565. with TClassDef(d) do begin
  566. if HasReplacedItems and not SecondPass then
  567. s:='protected'
  568. else
  569. s:='public';
  570. if CType = ctInterface then begin
  571. Fjs.WriteLn('private native long __AsIntf(long objptr);');
  572. ss:=IID;
  573. if ss = '' then
  574. ss:='null'
  575. else
  576. ss:='"' + ss + '"';
  577. Fjs.WriteLn(Format('%s %s(PascalObject obj) { super(0, true); __TypeCast(obj, %s); }', [s, AName, ss]));
  578. Fjs.WriteLn(Format('%s %s(long objptr) { super(objptr, true); }', [s, AName]));
  579. end
  580. else begin
  581. Fjs.WriteLn(Format('%s %s(PascalObject obj) { super(obj); }', [s, AName]));
  582. Fjs.WriteLn(Format('%s %s(long objptr) { super(objptr); }', [s, AName]));
  583. end;
  584. end;
  585. end;
  586. var
  587. s, ss, n: string;
  588. RegularClass: boolean;
  589. begin
  590. if PreInfo then begin
  591. WriteClassInfoVar(d);
  592. if d.CType in [ctObject, ctRecord] then begin
  593. s:=d.Parent.Name + '.' + d.Name;
  594. Fps.WriteLn;
  595. Fps.WriteLn(Format('function _%s_CreateObj(env: PJNIEnv; const r: %s): jobject;', [GetClassPrefix(d), s]));
  596. Fps.WriteLn(Format('var pr: ^%s;', [s]));
  597. Fps.WriteLn('begin');
  598. Fps.IncI;
  599. Fps.WriteLn(Format('pr:=AllocMem(SizeOf(%s)); pr^:=r;', [s]));
  600. Fps.WriteLn(Format('Result:=_CreateJavaObj(env, pr, %s);', [GetTypeInfoVar(d)]));
  601. Fps.DecI;
  602. Fps.WriteLn('end;');
  603. Fps.WriteLn;
  604. ss:=Format('_%s_Free', [GetClassPrefix(d)]);
  605. Fps.WriteLn(Format('procedure %s(env: PJNIEnv; _self: JObject; r: jlong);', [ss]) + JniCaliing);
  606. Fps.WriteLn(Format('var pr: ^%s;', [s]));
  607. Fps.WriteLn('begin');
  608. Fps.WriteLn('pr:=pointer(ptruint(r));', 1);
  609. Fps.WriteLn('system.Dispose(pr);', 1);
  610. Fps.WriteLn('end;');
  611. AddNativeMethod(d, ss, '__Destroy', '(J)V');
  612. end;
  613. exit;
  614. end;
  615. // Java
  616. case d.CType of
  617. ctInterface:
  618. s:='interface';
  619. ctObject:
  620. s:='interface';
  621. ctRecord:
  622. s:='record';
  623. else
  624. s:='class';
  625. end;
  626. WriteComment(d, s);
  627. n:=GetJavaClassName(d, nil);
  628. s:='public static class ' + n + ' extends ';
  629. with d do begin
  630. if AncestorClass <> nil then begin
  631. ss:=AncestorClass.Name;
  632. if ImplementsReplacedItems then
  633. ss:='__' + ss;
  634. s:=s + ss;
  635. end
  636. else
  637. if d.CType in [ctObject, ctRecord] then
  638. s:=s + Format('%s.system.Record', [JavaPackage])
  639. else
  640. if d.CType = ctInterface then
  641. s:=s + 'PascalInterface'
  642. else
  643. s:=s + 'PascalObject';
  644. end;
  645. Fjs.WriteLn(s + ' {');
  646. Fjs.IncI;
  647. case d.CType of
  648. ctObject, ctRecord:
  649. begin
  650. Fjs.WriteLn('private native void __Destroy(long pasobj);');
  651. if d.AncestorClass = nil then
  652. s:='__Init'
  653. else
  654. s:='super';
  655. Fjs.WriteLn(Format('protected %s(long objptr, boolean cleanup) { %s(objptr, cleanup); }', [d.Name, s]));
  656. Fjs.WriteLn(Format('public %s() { %s(0, true); }', [d.Name, s]));
  657. Fjs.WriteLn(Format('@Override public void __Release() { __Destroy(_pasobj); _pasobj=0; }', [d.Name]));
  658. Fjs.WriteLn(Format('@Override public int __Size() { return __Size(%d); }', [FRecords.Add(d)]));
  659. end;
  660. ctInterface:
  661. begin
  662. if d.AncestorClass = nil then begin
  663. Fjs.WriteLn('@Override public void __Release() { if (_pasobj != 0) _Release(); _pasobj = 0; }');
  664. Fjs.WriteLn('@Override protected void __Init() { _cleanup=true; if (_pasobj != 0) _AddRef(); }');
  665. end;
  666. Fjs.WriteLn(Format('protected %s(long objptr, boolean cleanup) { super(objptr, cleanup); }', [d.Name]));
  667. end;
  668. end;
  669. WriteTypeCast(n, False);
  670. WrittenItems:=TList.Create;
  671. try
  672. RegularClass:=(d.DefType = dtClass) and not TClassDef(d).HasReplacedItems;
  673. if RegularClass then
  674. WriteConstructors;
  675. // Write regular items
  676. WriteItems(True, False, RegularClass);
  677. if RegularClass and TClassDef(d).ImplementsReplacedItems then
  678. // Write implementation wrappers for replaced mehods
  679. WriteReplacedItems;
  680. Fjs.DecI;
  681. Fjs.WriteLn('}');
  682. Fjs.WriteLn;
  683. if (d.DefType = dtClass) and (TClassDef(d).HasReplacedItems) then begin
  684. // Write replaced items
  685. Fjs.WriteLn(Format('public static class %s extends __%0:s {', [d.AliasName]));
  686. Fjs.IncI;
  687. WriteTypeCast(d.AliasName, True);
  688. WriteConstructors;
  689. WriteItems(False, True, True);
  690. if TClassDef(d).ImplementsReplacedItems then
  691. // Write implementation wrappers for replaced mehods
  692. WriteReplacedItems;
  693. Fjs.DecI;
  694. Fjs.WriteLn('}');
  695. Fjs.WriteLn;
  696. end;
  697. finally
  698. WrittenItems.Free;
  699. end;
  700. end;
  701. procedure TWriter.WriteProc(d: TProcDef; Variable: TVarDef; AParent: TDef);
  702. var
  703. i, j, ClassIdx: integer;
  704. s, ss, ps, TempRes, VarFin: string;
  705. err, tf: boolean;
  706. pi: TProcInfo;
  707. ci: TClassInfo;
  708. IsTObject: boolean;
  709. tempvars: TStringList;
  710. vd: TVarDef;
  711. UseTempObjVar, IsObj, IsProcVar: boolean;
  712. ItemDef: TDef;
  713. begin
  714. ASSERT(d.DefType = dtProc);
  715. if d.IsPrivate or not d.IsUsed then
  716. exit;
  717. IsTObject:=(d.Parent.DefType = dtClass) and (TClassDef(d.Parent).AncestorClass = nil);
  718. if (d.ProcType = ptDestructor) and not IsTObject then
  719. exit;
  720. if Variable <> nil then
  721. ItemDef:=Variable
  722. else
  723. ItemDef:=d;
  724. tempvars:=nil;
  725. pi:=TProcInfo.Create;
  726. with d do
  727. try
  728. IsObj:=(d.Parent.DefType = dtClass) and (TClassDef(d.Parent).CType = ctObject);
  729. if not IsObj and (poClassMethod in ProcOpt) and (Name = 'ClassType') then
  730. ProcOpt:=ProcOpt - [poClassMethod];
  731. pi.Name:=Name;
  732. s:=GetClassPrefix(d.Parent) + pi.Name;
  733. pi.JniName:=s;
  734. pi.JniSignature:=GetProcSignature(d);
  735. if AParent = nil then begin
  736. // Checking duplicate proc name and duplicate param types
  737. ClassIdx:=FClasses.IndexOf(GetJavaClassName(d.Parent, ItemDef), d.Parent);
  738. if ClassIdx >= 0 then begin
  739. ci:=FClasses.GetClassInfo(ClassIdx);
  740. j:=1;
  741. ss:=Copy(pi.JniSignature, 1, Pos(')', pi.JniSignature));
  742. repeat
  743. err:=False;
  744. for i:=0 to ci.Funcs.Count - 1 do
  745. with TProcInfo(ci.Funcs[i]) do
  746. if CompareText(JniName, pi.JniName) = 0 then begin
  747. Inc(j);
  748. pi.JniName:=Format('%s_%d', [s, j]);
  749. err:=True;
  750. break;
  751. end
  752. else
  753. if (CompareText(Name, pi.Name) = 0) and (ss = Copy(JniSignature, 1, Pos(')', JniSignature))) then
  754. // Duplicate params
  755. exit;
  756. until not err;
  757. end;
  758. err:=False;
  759. if ProcType in [ptFunction, ptConstructor] then
  760. s:='function'
  761. else
  762. s:='procedure';
  763. s:=s + ' ' + pi.JniName + '(_env: PJNIEnv; _jobj: jobject';
  764. if IsObj and (ProcType in [ptConstructor, ptDestructor]) then
  765. TempRes:='__tempres';
  766. IsProcVar:=(Variable <> nil) and (Variable.VarType <> nil) and (Variable.VarType.DefType = dtProcType);
  767. UseTempObjVar:=IsProcVar and (ProcType = ptProcedure) and (Variable.Parent.DefType <> dtUnit);
  768. for j:=0 to Count - 1 do begin
  769. vd:=TVarDef(Items[j]);
  770. if vd.DefType <> dtParam then
  771. continue;
  772. with vd do begin
  773. if (VarType <> nil) and (VarType.DefType = dtJniEnv) then
  774. continue;
  775. s:=s + '; ' + Name + ': ';
  776. if not IsJavaVarParam(vd) then
  777. s:=s + DefToJniType(VarType, err)
  778. else begin
  779. s:=s + 'jarray';
  780. if tempvars = nil then
  781. tempvars:=TStringList.Create;
  782. if VarType = nil then
  783. err:=True
  784. else
  785. Tag:=tempvars.AddObject('__tmp_' + Name, d.Items[j]) + 1;
  786. end;
  787. end;
  788. end;
  789. s:=s + ')';
  790. if ProcType in [ptFunction, ptConstructor] then
  791. s:=s + ': ' + DefToJniType(ReturnType, err);
  792. s:=s + '; ' + JniCaliing;
  793. if err then begin
  794. s:='// ' + s;
  795. Fjs.WriteLn('// NOT PROCESSED: ' + GetJavaProcDeclaration(d));
  796. d.SetNotUsed;
  797. end;
  798. Fps.WriteLn;
  799. Fps.WriteLn(s);
  800. if err then
  801. exit;
  802. if (poClassMethod in ProcOpt) and not IsObj then begin
  803. Fps.WriteLn(Format('type _classt = %s;', [Parent.Parent.Name + '.' + Parent.Name]));
  804. Fps.WriteLn('type _class = class of _classt;');
  805. end;
  806. if (tempvars <> nil) or UseTempObjVar or (TempRes <> '') then begin
  807. s:='';
  808. Fps.WriteLn('var');
  809. Fps.IncI;
  810. if tempvars <> nil then begin
  811. for i:=0 to tempvars.Count - 1 do begin
  812. vd:=TVarDef(tempvars.Objects[i]);
  813. Fps.WriteLn(Format('%s: %s;', [tempvars[i], GetPasType(vd.VarType, True)]));
  814. if IsJavaSimpleType(vd.VarType) then begin
  815. Fps.WriteLn(Format('%s_arr: P%s;', [tempvars[i], DefToJniType(vd.VarType, err)]));
  816. if s = '' then
  817. s:='__iscopy: JBoolean;';
  818. end;
  819. end;
  820. if s <> '' then
  821. Fps.WriteLn(s);
  822. end;
  823. if UseTempObjVar then
  824. Fps.WriteLn('__objvar: ' + d.Parent.Name + ';');
  825. if TempRes <> '' then begin
  826. s:=TempRes + ': ';
  827. if IsObj and (ProcType in [ptConstructor, ptDestructor]) then
  828. s:=s + '^' + GetPasType(d.Parent, True)
  829. else
  830. s:=s + GetPasType(d.ReturnType, True);
  831. Fps.WriteLn(s + ';');
  832. end;
  833. Fps.DecI;
  834. end;
  835. if IsProcVar and (ProcType = ptProcedure) then
  836. Fps.WriteLn('var __mvar: TMethod;');
  837. Fps.WriteLn('begin');
  838. Fps.IncI;
  839. EHandlerStart;
  840. tf:=False;
  841. // Assign var parameter values to local vars
  842. if tempvars <> nil then begin
  843. for i:=0 to tempvars.Count - 1 do begin
  844. vd:=TVarDef(tempvars.Objects[i]);
  845. Fps.WriteLn(Format('if _env^^.GetArrayLength(_env, %s) <> 1 then _RaiseVarParamException(''%s'');', [vd.Name, vd.Name]));
  846. if IsJavaSimpleType(vd.VarType) then begin
  847. Fps.WriteLn(Format('%s_arr:=_env^^.Get%sArrayElements(_env, %s, __iscopy);', [tempvars[i], GetJniFuncType(vd.VarType), vd.Name]));
  848. Fps.WriteLn(Format('if %s_arr = nil then _RaiseVarParamException(''%s'');', [tempvars[i], vd.Name]));
  849. s:=tempvars[i] + '_arr^';
  850. tf:=True;
  851. end
  852. else
  853. s:=Format('_env^^.GetObjectArrayElement(_env, %s, 0)', [vd.Name]);
  854. if voVar in vd.VarOpt then
  855. Fps.WriteLn(tempvars[i] + ':=' + JniToPasType(vd.VarType, s, False) + ';');
  856. end;
  857. end;
  858. if tf then begin
  859. Fps.WriteLn('try');
  860. Fps.IncI;
  861. end;
  862. s:='';
  863. if not (IsObj and (ProcType in [ptConstructor, ptDestructor])) then
  864. if Parent.DefType = dtUnit then
  865. s:=Parent.Name + '.'
  866. else
  867. if ProcType = ptConstructor then
  868. s:=Parent.Parent.Name + '.' + Parent.Name + '.'
  869. else
  870. if (poClassMethod in ProcOpt) and not IsObj then
  871. s:='_class(_GetClass(_env, _jobj, ' + GetTypeInfoVar(d.Parent) + '))' + '.'
  872. else
  873. s:=JniToPasType(d.Parent, '_jobj', True) + '.';
  874. if Variable = nil then begin
  875. // Regular proc
  876. s:=s + pi.Name;
  877. if Count > 0 then begin
  878. s:=s + '(';
  879. ps:='';
  880. for j:=0 to Count - 1 do begin
  881. vd:=TVarDef(Items[j]);
  882. if vd.DefType <> dtParam then
  883. continue;
  884. if vd.VarType.DefType = dtJniEnv then
  885. ss:='_env'
  886. else
  887. if vd.Tag <> 0 then
  888. ss:=tempvars[vd.Tag - 1]
  889. else begin
  890. ss:=Items[j].Name;
  891. ss:=JniToPasType(vd.VarType, ss, False);
  892. end;
  893. if ps <> '' then
  894. ps:=ps + ', ';
  895. ps:=ps + ss;
  896. end;
  897. s:=s + ps + ')';
  898. end;
  899. end
  900. else begin
  901. // Var access
  902. if UseTempObjVar then begin
  903. System.Delete(s, Length(s), 1);
  904. Fps.WriteLn('__objvar:=' + s + ';');
  905. s:='__objvar.';
  906. end;
  907. s:=s + Variable.Name;
  908. j:=Count;
  909. if ProcType = ptProcedure then
  910. Dec(j);
  911. if j > 0 then begin
  912. i:=j;
  913. ss:='';
  914. for j:=0 to j - 1 do begin
  915. if ss <> '' then
  916. ss:=ss + ', ';
  917. ss:=ss + JniToPasType(TVarDef(Items[j]).VarType, Items[j].Name, False);
  918. end;
  919. s:=Format('%s[%s]', [s, ss]);
  920. end
  921. else
  922. i:=0;
  923. if ProcType = ptProcedure then begin
  924. ASSERT(Count = i + 1);
  925. if Variable.VarType.DefType = dtProcType then begin
  926. Fps.WriteLn(Format('__mvar:=TMethod(%s);', [s]));
  927. VarFin:=Format('_RefMethodPtr(_env, TMethod(%s), True); _RefMethodPtr(_env, __mvar, False);', [s]);
  928. end;
  929. s:=s + ':=' + JniToPasType(TVarDef(Items[i]).VarType, Items[i].Name, False);
  930. end;
  931. end;
  932. if IsObj and (ProcType = ptConstructor) then begin
  933. s:=Format('system.New(%s, %s);', [TempRes, s]);
  934. Fps.WriteLn(s);
  935. s:=Format('Result:=_CreateJavaObj(_env, %s, %s, False);', [TempRes, GetTypeInfoVar(ReturnType)]);
  936. Fps.WriteLn(s);
  937. end
  938. else
  939. if IsObj and (ProcType = ptDestructor) then begin
  940. Fps.WriteLn(TempRes + ':=@' + JniToPasType(d.Parent, '_jobj', True) + ';');
  941. Fps.WriteLn(Format('%s^.%s;', [TempRes, s]));
  942. Fps.WriteLn(Format('_env^^.SetLongField(_env, _jobj, %s.ObjFieldId, -jlong(ptruint(%s)));', [GetTypeInfoVar(d.Parent), TempRes]));
  943. end
  944. else begin
  945. if ProcType in [ptFunction, ptConstructor] then
  946. s:='Result:=' + PasToJniType(ReturnType, s);
  947. s:=s + ';';
  948. Fps.WriteLn(s);
  949. end;
  950. if VarFin <> '' then
  951. Fps.WriteLn(VarFin);
  952. // Return var/out parameters
  953. if tempvars <> nil then begin
  954. for i:=0 to tempvars.Count - 1 do begin
  955. vd:=TVarDef(tempvars.Objects[i]);
  956. if IsJavaSimpleType(vd.VarType) then
  957. Fps.WriteLn(Format('%s_arr^:=%s;', [tempvars[i], PasToJniType(vd.VarType, tempvars[i])]))
  958. else
  959. Fps.WriteLn(Format('_env^^.SetObjectArrayElement(_env, %s, 0, %s);', [vd.Name, PasToJniType(vd.VarType, tempvars[i])]));
  960. end;
  961. end;
  962. if not IsObj then
  963. if IsTObject and ( (ProcType = ptDestructor) or (CompareText(Name, 'Free') = 0) ) then
  964. Fps.WriteLn(Format('_env^^.SetLongField(_env, _jobj, %s.ObjFieldId, 0);', [GetTypeInfoVar(d.Parent)]));
  965. if tf then begin
  966. Fps.WriteLn('finally', -1);
  967. if tempvars <> nil then begin
  968. for i:=0 to tempvars.Count - 1 do begin
  969. vd:=TVarDef(tempvars.Objects[i]);
  970. if IsJavaSimpleType(vd.VarType) then
  971. Fps.WriteLn(Format('_env^^.Release%sArrayElements(_env, %s, %s_arr, 0);', [GetJniFuncType(vd.VarType), vd.Name, tempvars[i]]));
  972. end;
  973. end;
  974. Fps.DecI;
  975. Fps.WriteLn('end;');
  976. end;
  977. s:='';
  978. if ProcType in [ptFunction, ptConstructor] then begin
  979. s:='0';
  980. if (ReturnType.DefType = dtType) and (TTypeDef(ReturnType).BasicType <= btDouble) then
  981. s:='0'
  982. else
  983. s:=Format('%s(0)', [DefToJniType(ReturnType, err)]);
  984. s:='Result:=' + s + ';';
  985. end;
  986. EHandlerEnd('_env', s);
  987. Fps.DecI;
  988. Fps.WriteLn('end;');
  989. AParent:=d.Parent;
  990. end
  991. else
  992. ClassIdx:=FClasses.IndexOf(GetJavaClassName(AParent, ItemDef), AParent);
  993. if ClassIdx < 0 then begin
  994. ci:=TClassInfo.Create;
  995. ci.Def:=AParent;
  996. s:=GetJavaClassName(AParent, ItemDef);
  997. ci.IsCommonClass:=s <> AParent.Name;
  998. ClassIdx:=FClasses.Add(s, AParent, ci);
  999. end;
  1000. FClasses.GetClassInfo(ClassIdx).Funcs.Add(pi);
  1001. pi:=nil;
  1002. // Java part
  1003. s:=GetJavaProcDeclaration(d) + ';';
  1004. if (Parent.DefType = dtUnit) or (ProcType = ptConstructor) then
  1005. s:='static ' + s;
  1006. if Variable = nil then
  1007. Fjs.WriteLn('// ' + GetProcDeclaration(d));
  1008. if poPrivate in ProcOpt then
  1009. ss:='private'
  1010. else
  1011. if poProtected in ProcOpt then
  1012. ss:='protected'
  1013. else
  1014. ss:='public';
  1015. Fjs.WriteLn(ss + ' native ' + s);
  1016. finally
  1017. pi.Free;
  1018. tempvars.Free;
  1019. end;
  1020. end;
  1021. procedure TWriter.WriteVar(d: TVarDef; AParent: TDef);
  1022. function _WriteArrayIndex(pd: TProcDef): TDef;
  1023. var
  1024. ad: TArrayDef;
  1025. i: integer;
  1026. begin
  1027. ad:=TArrayDef(d.VarType);
  1028. i:=1;
  1029. repeat
  1030. with TVarDef.Create(pd, dtParam) do begin
  1031. Name:='Index';
  1032. if i > 1 then
  1033. Name:=Name + IntToStr(i);
  1034. VarType:=ad.RangeType;
  1035. if (VarType.DefType = dtType) and (TTypeDef(VarType).BasicType in [btByte, btShortInt, btSmallInt]) then
  1036. VarType:=FIntegerType;
  1037. VarOpt:=[voRead];
  1038. IsUsed:=True;
  1039. end;
  1040. Result:=ad.ElType;
  1041. ad:=TArrayDef(Result);
  1042. Inc(i);
  1043. until Result.DefType <> dtArray;
  1044. end;
  1045. var
  1046. pd: TProcDef;
  1047. vd: TVarDef;
  1048. t: TTypeDef;
  1049. vt: TDef;
  1050. s, ss: string;
  1051. i: integer;
  1052. isarray, isdynarray: boolean;
  1053. begin
  1054. if not d.IsUsed then
  1055. exit;
  1056. isarray:=(d.VarType <> nil) and (d.VarType.DefType = dtArray);
  1057. isdynarray:=isarray and (TArrayDef(d.VarType).RangeHigh < TArrayDef(d.VarType).RangeLow);
  1058. if isdynarray then
  1059. if not (voRead in d.VarOpt) then
  1060. exit
  1061. else
  1062. d.VarOpt:=d.VarOpt + [voWrite];
  1063. if d.VarType <> nil then begin
  1064. case d.DefType of
  1065. dtVar:
  1066. s:='var';
  1067. dtProp:
  1068. s:='property';
  1069. else
  1070. s:='';
  1071. end;
  1072. s:=Trim(s + ' ' + d.Name);
  1073. if d.Count > 0 then
  1074. s:=s + '[]';
  1075. ss:=d.VarType.Name;
  1076. if ss = '' then
  1077. if d.VarType.DefType = dtArray then
  1078. ss:='array';
  1079. Fjs.WriteLn(Format('// %s: %s', [s, ss]));
  1080. end;
  1081. if voRead in d.VarOpt then begin
  1082. pd:=TProcDef.Create(nil, dtProc);
  1083. try
  1084. pd.IsUsed:=True;
  1085. pd.Parent:=d.Parent;
  1086. pd.ProcType:=ptFunction;
  1087. pd.Name:='get' + d.Name;
  1088. if isarray then
  1089. // Array var
  1090. pd.ReturnType:=_WriteArrayIndex(pd)
  1091. else begin
  1092. pd.ReturnType:=d.VarType;
  1093. if d.DefType = dtProp then begin
  1094. for i:=0 to d.Count - 1 do begin
  1095. vd:=TVarDef(d.Items[i]);
  1096. with TVarDef.Create(pd, dtParam) do begin
  1097. Name:=vd.Name;
  1098. VarType:=vd.VarType;
  1099. VarOpt:=[voRead];
  1100. end;
  1101. end;
  1102. end;
  1103. end;
  1104. WriteProc(pd, d, AParent);
  1105. finally
  1106. pd.Free;
  1107. end;
  1108. end;
  1109. if voWrite in d.VarOpt then begin
  1110. pd:=TProcDef.Create(nil, dtProc);
  1111. try
  1112. pd.IsUsed:=True;
  1113. pd.Parent:=d.Parent;
  1114. pd.ProcType:=ptProcedure;
  1115. pd.Name:='set' + d.Name;
  1116. vt:=d.VarType;;
  1117. if isarray then begin
  1118. // Array var
  1119. if (d.DefType = dtProp) and not isdynarray then
  1120. exit;
  1121. vt:=_WriteArrayIndex(pd);
  1122. end
  1123. else
  1124. if d.DefType = dtProp then begin
  1125. for i:=0 to d.Count - 1 do begin
  1126. vd:=TVarDef(d.Items[i]);
  1127. with TVarDef.Create(pd, dtParam) do begin
  1128. Name:=vd.Name;
  1129. VarType:=vd.VarType;
  1130. VarOpt:=[voRead];
  1131. end;
  1132. end;
  1133. end;
  1134. s:='Value';
  1135. // Check if the name of value parameter is unique
  1136. i:=0;
  1137. while i < d.Count do begin
  1138. if AnsiCompareText(s, d.Items[i].AliasName) = 0 then begin
  1139. i:=0;
  1140. s:='_' + s;
  1141. continue;
  1142. end;
  1143. Inc(i);
  1144. end;
  1145. with TVarDef.Create(pd, dtParam) do begin
  1146. Name:=s;
  1147. VarType:=vt;
  1148. VarOpt:=[voRead];
  1149. end;
  1150. t:=TTypeDef.Create(nil, dtType);
  1151. try
  1152. t.BasicType:=btVoid;
  1153. pd.ReturnType:=t;
  1154. WriteProc(pd, d, AParent);
  1155. finally
  1156. t.Free;
  1157. end;
  1158. finally
  1159. pd.Free;
  1160. end;
  1161. end;
  1162. end;
  1163. procedure TWriter.WriteConst(d: TConstDef);
  1164. var
  1165. s, v: string;
  1166. begin
  1167. if not d.IsUsed then
  1168. exit;
  1169. v:=d.Value;
  1170. if d.VarType = nil then begin
  1171. if Copy(d.Value, 1, 1) = '"' then
  1172. s:='String'
  1173. else
  1174. s:='double';
  1175. end
  1176. else begin
  1177. s:='';
  1178. case d.VarType.DefType of
  1179. dtType:
  1180. case TTypeDef(d.VarType).BasicType of
  1181. btLongWord, btInt64:
  1182. v:=v + 'L';
  1183. btBoolean:
  1184. if v = '1' then
  1185. v:='true'
  1186. else
  1187. v:='false';
  1188. end;
  1189. dtArray:
  1190. with TArrayDef(d.VarType) do
  1191. if (ElType.DefType = dtType) and (TTypeDef(ElType).BasicType in [btChar, btWideChar]) then
  1192. s:='String';
  1193. end;
  1194. if s = '' then
  1195. s:=DefToJavaType(d.VarType);
  1196. end;
  1197. v:=Format('public static final %s %s = %s;', [s, d.Name, v]);
  1198. if s = SUnsupportedType then
  1199. v:='// ' + v;
  1200. Fjs.WriteLn(v);
  1201. end;
  1202. procedure TWriter.WriteEnum(d: TDef);
  1203. var
  1204. i: integer;
  1205. s: string;
  1206. begin
  1207. if not d.IsUsed then
  1208. exit;
  1209. RegisterPseudoClass(d);
  1210. WriteComment(d, 'enum');
  1211. Fjs.WriteLn(Format('public static class %s extends %s.system.Enum {', [d.Name, JavaPackage]));
  1212. Fjs.IncI;
  1213. for i:=0 to d.Count - 1 do begin
  1214. s:=Format('public final static int %s = %s;', [d[i].Name, TConstDef(d[i]).Value]);
  1215. Fjs.WriteLn(s);
  1216. end;
  1217. Fjs.WriteLn;
  1218. for i:=0 to d.Count - 1 do begin
  1219. s:=Format('public static %s %s() { return new %0:s(%1:s); }', [d.Name, d[i].Name]);
  1220. Fjs.WriteLn(s);
  1221. end;
  1222. Fjs.WriteLn;
  1223. Fjs.WriteLn(Format('public %s(int v) { Value = v; }', [d.Name]));
  1224. Fjs.WriteLn(Format('@Override public boolean equals(Object o) { return ((o instanceof %0:s) && Value == ((%0:s)o).Value) || super.equals(o); }', [d.Name]));
  1225. Fjs.DecI;
  1226. Fjs.WriteLn('}');
  1227. Fjs.WriteLn;
  1228. end;
  1229. procedure TWriter.WriteProcType(d: TProcDef; PreInfo: boolean);
  1230. procedure _AccessSimpleArray(vd: TVarDef; VarIndex: integer; DoSet: boolean);
  1231. begin
  1232. with vd do begin
  1233. Fps.WriteLn(Format('_tmp_%s:=_env^^.Get%sArrayElements(_env, _args[%d].L, PJBoolean(nil)^);', [Name, GetJniFuncType(VarType), VarIndex]));
  1234. Fps.WriteLn(Format('if _tmp_%s <> nil then', [Name]));
  1235. if DoSet then
  1236. Fps.WriteLn(Format('_tmp_%s^:=%s;', [Name, PasToJniType(VarType, Name)]), 1)
  1237. else
  1238. Fps.WriteLn(Format('%s:=%s;', [Name, JniToPasType(VarType, '_tmp_' + Name + '^', False)]), 1);
  1239. Fps.WriteLn(Format('_env^^.Release%sArrayElements(_env, _args[%d].L, _tmp_%s, 0);', [GetJniFuncType(VarType), VarIndex, Name]));
  1240. end;
  1241. end;
  1242. var
  1243. vd: TVarDef;
  1244. i: integer;
  1245. s, ss, hclass: string;
  1246. err: boolean;
  1247. begin
  1248. if not d.IsUsed or not (poMethodPtr in d.ProcOpt) then
  1249. exit;
  1250. if PreInfo then begin
  1251. WriteClassInfoVar(d);
  1252. // Handler proc
  1253. hclass:=GetClassPrefix(d) + 'Class';
  1254. Fps.WriteLn;
  1255. Fps.WriteLn(Format('type %s = class', [hclass]));
  1256. Fps.WriteLn(Format('private %s;', [ GetProcDeclaration(d, 'Handler', True, True)]), 1);
  1257. Fps.WriteLn('end;');
  1258. Fps.WriteLn;
  1259. Fps.WriteLn(GetProcDeclaration(d, Format('%s.Handler', [hclass]), True, True) + ';');
  1260. Fps.WriteLn('var');
  1261. Fps.IncI;
  1262. Fps.WriteLn('_env: PJNIEnv;');
  1263. Fps.WriteLn('_new_env: boolean;');
  1264. Fps.WriteLn('_mpi: _TMethodPtrInfo;');
  1265. if d.Count > 0 then begin
  1266. Fps.WriteLn(Format('_args: array[0..%d] of jvalue;', [d.Count - 1]));
  1267. for i:=0 to d.Count - 1 do begin
  1268. vd:=TVarDef(d[i]);
  1269. if vd.DefType <> dtParam then
  1270. continue;
  1271. with vd do
  1272. if IsJavaVarParam(vd) and IsJavaSimpleType(VarType) then
  1273. Fps.WriteLn(Format('_tmp_%s: P%s;', [Name, DefToJniType(VarType, err)]));
  1274. end;
  1275. end;
  1276. Fps.DecI;
  1277. Fps.WriteLn('begin');
  1278. Fps.IncI;
  1279. Fps.WriteLn('CurJavaVM^^.GetEnv(CurJavaVM, @_env, JNI_VERSION_1_6);');
  1280. Fps.WriteLn('_new_env:=_env = nil;');
  1281. Fps.WriteLn('if _new_env then CurJavaVM^^.AttachCurrentThread(CurJavaVM, @_env, nil);');
  1282. Fps.WriteLn('_env^^.PushLocalFrame(_env, 100);');
  1283. Fps.WriteLn('try');
  1284. Fps.IncI;
  1285. Fps.WriteLn('_MethodPointersCS.Enter;');
  1286. Fps.WriteLn('try');
  1287. Fps.WriteLn('_mpi:=_TMethodPtrInfo(_MethodPointers[-integer(ptruint(Self)) - 1]);', 1);
  1288. Fps.WriteLn('finally');
  1289. Fps.WriteLn('_MethodPointersCS.Leave;', 1);
  1290. Fps.WriteLn('end;');
  1291. for i:=0 to d.Count - 1 do begin
  1292. vd:=TVarDef(d[i]);
  1293. if vd.DefType <> dtParam then
  1294. continue;
  1295. with vd do begin
  1296. if not IsJavaVarParam(vd) then begin
  1297. s:='L';
  1298. if VarType.DefType = dtType then
  1299. s:=Copy(JNITypeSig[TTypeDef(VarType).BasicType], 1, 1);
  1300. ss:=PasToJniType(VarType, Name);
  1301. end
  1302. else begin
  1303. s:='L';
  1304. if IsJavaSimpleType(VarType) then
  1305. ss:=Format('_env^^.New%sArray(_env, 1)', [GetJniFuncType(VarType)])
  1306. else begin
  1307. if voVar in VarOpt then
  1308. ss:=PasToJniType(VarType, Name)
  1309. else
  1310. ss:='nil';
  1311. ss:=Format('_env^^.NewObjectArray(_env, 1, %s.ClassRef, %s)', [GetTypeInfoVar(VarType), ss]);
  1312. end;
  1313. end;
  1314. Fps.WriteLn(Format('_args[%d].%s:=%s;', [i, s, ss]));
  1315. if IsJavaVarParam(vd) and (voVar in VarOpt) and IsJavaSimpleType(VarType) then
  1316. _AccessSimpleArray(TVarDef(d[i]), i, True);
  1317. end;
  1318. end;
  1319. if d.Count > 0 then
  1320. s:='@_args'
  1321. else
  1322. s:='nil';
  1323. // Calling Java handler
  1324. s:=Format('_env^^.Call%sMethodA(_env, _mpi.Obj, _mpi.MethodId, %s)', [GetJniFuncType(d.ReturnType), s]);
  1325. if d.ProcType = ptFunction then
  1326. s:=Format('Result:=%s', [JniToPasType(d.ReturnType, s, False)]);
  1327. Fps.WriteLn(s + ';');
  1328. // Java exception check
  1329. Fps.WriteLn('_HandleJavaException(_env);');
  1330. // Processing var/out parameters
  1331. for i:=0 to d.Count - 1 do begin
  1332. vd:=TVarDef(d[i]);
  1333. if vd.DefType <> dtParam then
  1334. continue;
  1335. with vd do
  1336. if IsJavaVarParam(vd) then
  1337. if IsJavaSimpleType(VarType) then
  1338. _AccessSimpleArray(TVarDef(d[i]), i, False)
  1339. else begin
  1340. s:=Format('_env^^.GetObjectArrayElement(_env, _args[%d].L, 0)', [i]);
  1341. Fps.WriteLn(Format('%s:=%s;', [Name, JniToPasType(VarType, s, False)]));
  1342. end;
  1343. end;
  1344. Fps.DecI;
  1345. Fps.WriteLn('finally');
  1346. Fps.WriteLn('_env^^.PopLocalFrame(_env, nil);', 1);
  1347. Fps.WriteLn('if _new_env then CurJavaVM^^.DetachCurrentThread(CurJavaVM);', 1);
  1348. Fps.WriteLn('end;');
  1349. Fps.DecI;
  1350. Fps.WriteLn('end;');
  1351. // Get handler proc
  1352. Fps.WriteLn;
  1353. Fps.WriteLn(Format('function %sGetHandler(env: PJNIEnv; jobj: jobject; const ci: _TJavaClassInfo): %s.%s;',
  1354. [GetClassPrefix(d), d.Parent.Name, d.Name]));
  1355. Fps.WriteLn('begin');
  1356. Fps.WriteLn(Format('TMethod(Result):=_GetMethodPtrHandler(env, jobj, @%s.Handler, %s);', [hclass, GetTypeInfoVar(d)]), 1);
  1357. Fps.WriteLn('end;');
  1358. exit;
  1359. end;
  1360. err:=False;
  1361. WriteComment(d, 'procedural type');
  1362. RegisterPseudoClass(d);
  1363. Fjs.WriteLn(Format('/* Pascal prototype: %s */', [GetProcDeclaration(d, 'Execute')]));
  1364. Fjs.WriteLn(Format('/* Java prototype: %s */', [GetJavaProcDeclaration(d, 'Execute')]));
  1365. Fjs.WriteLn(Format('public static class %s extends %s.system.MethodPtr {', [d.Name, JavaPackage]));
  1366. Fjs.IncI;
  1367. Fjs.WriteLn(Format('{ mSignature = "%s"; }', [GetProcSignature(d)]));
  1368. Fjs.WriteLn(Format('protected %s(long objptr, boolean cleanup) { _pasobj=objptr; }', [d.Name]));
  1369. Fjs.WriteLn(Format('@Deprecated public %s(Object Obj, String MethodName) { mObject=Obj; mName=MethodName; }', [d.Name]));
  1370. Fjs.WriteLn(Format('public %s() { mObject=this; mName="Execute"; }', [d.Name]));
  1371. Fjs.WriteLn(Format('protected %s throws NoSuchMethodException { throw new NoSuchMethodException(); }', [GetJavaProcDeclaration(d, 'Execute')]));
  1372. Fjs.DecI;
  1373. Fjs.WriteLn('}');
  1374. Fjs.WriteLn;
  1375. end;
  1376. procedure TWriter.WriteSet(d: TSetDef);
  1377. begin
  1378. if not d.IsUsed then
  1379. exit;
  1380. if d.ElType = nil then
  1381. raise Exception.Create('No element type.');
  1382. WriteComment(d, '');
  1383. Fjs.WriteLn(Format('/* set of %s */', [d.ElType.Name]));
  1384. if d.Size > 4 then begin
  1385. Fjs.WriteLn('/* Set size more than 32 bits is not supported */');
  1386. exit;
  1387. end;
  1388. RegisterPseudoClass(d);
  1389. Fjs.WriteLn(Format('public static class %s extends %s.system.Set<%s,%s> {', [d.Name, JavaPackage, d.Name, d.ElType.Name]));
  1390. Fjs.IncI;
  1391. Fjs.WriteLn(Format('@Override protected byte Size() { return %d; }', [d.Size]));
  1392. Fjs.WriteLn(Format('@Override protected int Base() { return %d; }', [d.Base]));
  1393. Fjs.WriteLn(Format('@Override protected int ElMax() { return %d; }', [d.ElMax]));
  1394. Fjs.WriteLn(Format('public %s() { }', [d.Name]));
  1395. Fjs.WriteLn(Format('public %s(%s... Elements) { super(Elements); }', [d.Name, d.ElType.Name]));
  1396. Fjs.WriteLn(Format('public %0:s(%0:s... Elements) { super(Elements); }', [d.Name]));
  1397. Fjs.WriteLn(Format('public static %0:s Exclude(%0:s s1, %0:s s2) { %0:s r = new %0:s(s1); r.Exclude(s2); return r; }', [d.Name]));
  1398. Fjs.WriteLn(Format('public static %0:s Intersect(%0:s s1, %0:s s2) { %0:s r = new %0:s(s1); r.Intersect(s2); return r; }', [d.Name]));
  1399. Fjs.DecI;
  1400. Fjs.WriteLn('}');
  1401. Fjs.WriteLn;
  1402. end;
  1403. procedure TWriter.WritePointer(d: TPointerDef; PreInfo: boolean);
  1404. begin
  1405. if not d.IsUsed or not d.IsObjPtr then
  1406. exit;
  1407. if PreInfo then begin
  1408. RegisterPseudoClass(d);
  1409. WriteClassInfoVar(d);
  1410. exit;
  1411. end;
  1412. WriteComment(d, 'pointer');
  1413. Fjs.WriteLn(Format('public static class %s extends %s {', [d.Name, d.PtrType.Name]));
  1414. Fjs.IncI;
  1415. if TClassDef(d.PtrType).CType in [ctObject, ctRecord] then
  1416. Fjs.WriteLn(Format('protected %s(long objptr, boolean cleanup) { super(objptr, false); }', [d.Name]));
  1417. Fjs.WriteLn(Format('public %s(PascalObject obj) { super(obj); }', [d.Name]));
  1418. Fjs.WriteLn(Format('public %s(long objptr) { super(objptr); }', [d.Name]));
  1419. Fjs.DecI;
  1420. Fjs.WriteLn('}');
  1421. Fjs.WriteLn;
  1422. end;
  1423. procedure TWriter.WriteClassRef(d: TClassRefDef; PreInfo: boolean);
  1424. begin
  1425. if not d.IsUsed then
  1426. exit;
  1427. if PreInfo then begin
  1428. RegisterPseudoClass(d);
  1429. WriteClassInfoVar(d);
  1430. exit;
  1431. end;
  1432. WriteComment(d, 'class ref');
  1433. Fjs.WriteLn(Format('public static class %s extends %s {', [d.Name, d.ClassRef.Name]));
  1434. Fjs.IncI;
  1435. Fjs.WriteLn(Format('public %s(PascalObject obj) { super(obj); }', [d.Name]));
  1436. Fjs.DecI;
  1437. Fjs.WriteLn('}');
  1438. Fjs.WriteLn;
  1439. end;
  1440. procedure TWriter.WriteUnit(u: TUnitDef);
  1441. procedure _ProcessExcludedProcParams(d: TDef);
  1442. var
  1443. i: integer;
  1444. begin
  1445. if not d.IsUsed then
  1446. exit;
  1447. if d.DefType in [dtProc, dtProcType] then begin
  1448. for i:=0 to d.Count - 1 do
  1449. if d[i].DefType = dtParam then
  1450. with TVarDef(d[i]) do
  1451. if (VarType <> nil) and not VarType.IsUsed then begin
  1452. d.SetNotUsed;
  1453. break;
  1454. end;
  1455. end
  1456. else
  1457. for i:=0 to d.Count - 1 do
  1458. _ProcessExcludedProcParams(d[i]);
  1459. end;
  1460. var
  1461. d: TDef;
  1462. i: integer;
  1463. f: boolean;
  1464. begin
  1465. if u.Processed then
  1466. exit;
  1467. u.Processed:=True;
  1468. if not u.IsUsed then
  1469. exit;
  1470. _ProcessExcludedProcParams(u);
  1471. for i:=0 to High(u.UsedUnits) do
  1472. WriteUnit(u.UsedUnits[i]);
  1473. Fps.WriteLn;
  1474. Fps.WriteLn(Format('{ Unit %s }', [u.Name]));
  1475. u.Name:=LowerCase(u.Name);
  1476. Fjs:=TTextOutStream.Create(IncludeTrailingPathDelimiter(FPkgDir) + u.Name + '.java', fmCreate);
  1477. try
  1478. WriteFileComment(Fjs);
  1479. Fjs.WriteLn(Format('package %s;', [JavaPackage]));
  1480. if Length(u.UsedUnits) > 0 then begin
  1481. UpdateUsedUnits(u);
  1482. f:=False;
  1483. for i:=0 to High(u.UsedUnits) do
  1484. if u.UsedUnits[i].IsUnitUsed then begin
  1485. if not f then begin
  1486. Fjs.WriteLn;
  1487. f:=True;
  1488. end;
  1489. Fjs.WriteLn(Format('import %s.%s.*;', [JavaPackage, LowerCase(u.UsedUnits[i].Name)]));
  1490. end;
  1491. end;
  1492. if u.Name = 'system' then begin
  1493. Fjs.WriteLn;
  1494. Fjs.WriteLn('import java.util.Date;');
  1495. Fjs.WriteLn('import java.util.TimeZone;');
  1496. end;
  1497. Fjs.WriteLn;
  1498. Fjs.WriteLn('public class ' + u.Name + ' {');
  1499. Fjs.IncI;
  1500. if u.Name = 'system' then begin
  1501. for i:=0 to u.Count - 1 do begin
  1502. d:=u[i];
  1503. if (d.DefType = dtType) and (TTypeDef(d).BasicType = btLongInt) and (Copy(d.Name, 1, 1) <> '$') then begin
  1504. FIntegerType:=d;
  1505. break;
  1506. end;
  1507. end;
  1508. if FIntegerType = nil then
  1509. raise Exception.Create('LongInt type has not been found in the System unit.');
  1510. if LibAutoLoad then begin
  1511. Fjs.WriteLn('static private boolean _JniLibLoaded = false;');
  1512. Fjs.WriteLn('public static void InitJni() {');
  1513. Fjs.WriteLn('if (!_JniLibLoaded) {', 1);
  1514. Fjs.WriteLn('_JniLibLoaded=true;', 2);
  1515. Fjs.WriteLn(Format('System.loadLibrary("%s");', [LibName]), 2);
  1516. Fjs.WriteLn('}', 1);
  1517. Fjs.WriteLn('}');
  1518. end;
  1519. // Public support functions
  1520. Fjs.WriteLn('public native static long AllocMemory(int Size);');
  1521. AddNativeMethod(u, '_AllocMemory', 'AllocMemory', '(I)J');
  1522. Fjs.WriteLn('public native static byte[] GetMemoryAsArray(long SrcBuf, int BufSize);');
  1523. AddNativeMethod(u, '_GetMemoryAsArray', 'GetMemoryAsArray', '(JI)[B');
  1524. Fjs.WriteLn('public native static void SetMemoryFromArray(long DstBuf, byte[] SrcArray);');
  1525. AddNativeMethod(u, '_SetMemoryFromArray', 'SetMemoryFromArray', '(J[B)V');
  1526. // Base object
  1527. Fjs.WriteLn;
  1528. Fjs.WriteLn('public static class PascalObject {');
  1529. Fjs.IncI;
  1530. if LibAutoLoad then
  1531. Fjs.WriteLn(Format('static { %s.system.InitJni(); }', [JavaPackage]));
  1532. Fjs.WriteLn('protected long _pasobj = 0;');
  1533. Fjs.WriteLn('protected PascalObject() { }');
  1534. Fjs.WriteLn('protected PascalObject(PascalObject obj) { if (obj != null) _pasobj=obj._pasobj; }');
  1535. Fjs.WriteLn('protected PascalObject(long objptr) { _pasobj=objptr; }');
  1536. Fjs.WriteLn('@Override protected void finalize() { }');
  1537. Fjs.WriteLn('@Override public boolean equals(Object o) { return ((o instanceof PascalObject) && _pasobj == ((PascalObject)o)._pasobj); }');
  1538. Fjs.WriteLn('@Override public int hashCode() { return (int)_pasobj; }');
  1539. Fjs.DecI;
  1540. Fjs.WriteLn('}');
  1541. Fjs.WriteLn;
  1542. Fjs.WriteLn('public static long Pointer(PascalObject obj) { return (obj == null) ? 0 : obj._pasobj; }');
  1543. // Object with finalization
  1544. Fjs.WriteLn;
  1545. Fjs.WriteLn('public static class PascalObjectEx extends PascalObject {');
  1546. Fjs.IncI;
  1547. Fjs.WriteLn('protected boolean _cleanup = false;');
  1548. Fjs.WriteLn('@Override protected void finalize() { ');
  1549. {$ifdef DEBUG}
  1550. Fjs.WriteLn('String s = "finalize(): " + getClass().getName(); if (_cleanup) s=s+". Need __Release(). ptr="+_pasobj; System.out.println(s);', 1);
  1551. {$endif DEBUG}
  1552. Fjs.WriteLn('if (_cleanup) __Release();', 1);
  1553. Fjs.WriteLn('super.finalize();', 1);
  1554. Fjs.WriteLn('}');
  1555. Fjs.WriteLn('protected PascalObjectEx() { }');
  1556. Fjs.WriteLn('protected PascalObjectEx(PascalObject obj) { super(obj); }');
  1557. Fjs.WriteLn('protected PascalObjectEx(long objptr) { super(objptr); }');
  1558. Fjs.WriteLn('public void __Release() { _pasobj = 0; }');
  1559. Fjs.DecI;
  1560. Fjs.WriteLn('}');
  1561. // Record
  1562. Fjs.WriteLn;
  1563. Fjs.WriteLn('public static class Record extends PascalObjectEx {');
  1564. Fjs.IncI;
  1565. Fjs.WriteLn('protected PascalObject _objref;');
  1566. Fjs.WriteLn('@Override protected void finalize() { if (_pasobj < 0) { _pasobj=-_pasobj; _cleanup=true; } super.finalize(); }');
  1567. Fjs.WriteLn('protected void __Init(long objptr, boolean cleanup) { _pasobj=objptr; _cleanup=cleanup; if (_pasobj==0 && __Size() != 0) _pasobj=AllocMemory(__Size()); }');
  1568. Fjs.WriteLn('protected Record(PascalObject obj) { super(obj); _objref=obj; }');
  1569. Fjs.WriteLn('protected Record(long objptr) { super(objptr); }');
  1570. Fjs.WriteLn('protected final int __Size(int index) { return GetRecordSize(index); }');
  1571. Fjs.WriteLn('public Record() { }');
  1572. Fjs.WriteLn('public int __Size() { return 0; }');
  1573. Fjs.DecI;
  1574. Fjs.WriteLn('}');
  1575. Fjs.WriteLn;
  1576. Fjs.WriteLn('private native static int GetRecordSize(int index);');
  1577. AddNativeMethod(u, '_GetRecordSize', 'GetRecordSize', '(I)I');
  1578. // Method pointer base class
  1579. d:=TClassDef.Create(FThisUnit, dtClass);
  1580. d.Name:='_TMethodPtrInfo';
  1581. d.AliasName:='MethodPtr';
  1582. WriteClassInfoVar(d);
  1583. // Method pointer support
  1584. Fps.WriteLn;
  1585. Fps.WriteLn('type');
  1586. Fps.IncI;
  1587. Fps.WriteLn('_TMethodPtrInfo = class');
  1588. Fps.IncI;
  1589. Fps.WriteLn('Obj: JObject;');
  1590. Fps.WriteLn('MethodId: JMethodID;');
  1591. Fps.WriteLn('Index, RefCnt: integer;');
  1592. Fps.WriteLn('RealMethod: TMethod;');
  1593. Fps.WriteLn('InlineHandler: boolean;');
  1594. Fps.WriteLn('constructor Create(env: PJNIEnv; JavaObj: JObject; const AMethodName, AMethodSig: ansistring);');
  1595. Fps.WriteLn('procedure Release(env: PJNIEnv);');
  1596. Fps.DecI;
  1597. Fps.WriteLn('end;');
  1598. Fps.DecI;
  1599. Fps.WriteLn;
  1600. Fps.WriteLn('var _MethodPointers: array of _TMethodPtrInfo;');
  1601. Fps.WriteLn('var _MethodPointersCS: TCriticalSection;');
  1602. Fps.WriteLn;
  1603. Fps.WriteLn('constructor _TMethodPtrInfo.Create(env: PJNIEnv; JavaObj: JObject; const AMethodName, AMethodSig: ansistring);');
  1604. Fps.WriteLn('var c: JClass;');
  1605. Fps.WriteLn('begin');
  1606. Fps.IncI;
  1607. Fps.WriteLn('if (JavaObj = nil) or (AMethodName = '''') then exit;');
  1608. Fps.WriteLn('c:=env^^.GetObjectClass(env, JavaObj);');
  1609. Fps.WriteLn('if c = nil then exit;');
  1610. Fps.WriteLn('MethodId:=env^^.GetMethodID(env, c, PAnsiChar(AMethodName), PAnsiChar(AMethodSig));');
  1611. Fps.WriteLn('if MethodId = nil then raise Exception.CreateFmt(''Method "%s" does not exist or has wrong parameters.'', [AMethodName]);');
  1612. Fps.WriteLn('Obj:=env^^.NewGlobalRef(env, JavaObj);');
  1613. Fps.WriteLn('_MethodPointersCS.Enter;');
  1614. Fps.WriteLn('try');
  1615. Fps.IncI;
  1616. Fps.WriteLn('Index:=Length(_MethodPointers) + 1;');
  1617. Fps.WriteLn(Format('if Index > %d then raise Exception.Create(''Too many method pointers.'');', [MaxMethodPointers]));
  1618. Fps.WriteLn('SetLength(_MethodPointers, Index);');
  1619. Fps.WriteLn('_MethodPointers[Index - 1]:=Self;');
  1620. Fps.WriteLn('finally', -1);
  1621. Fps.WriteLn('_MethodPointersCS.Leave;');
  1622. Fps.DecI;
  1623. Fps.WriteLn('end;');
  1624. Fps.DecI;
  1625. Fps.WriteLn('end;');
  1626. Fps.WriteLn;
  1627. Fps.WriteLn('procedure _TMethodPtrInfo.Release(env: PJNIEnv);');
  1628. Fps.WriteLn('var i: integer;');
  1629. Fps.WriteLn('begin');
  1630. Fps.IncI;
  1631. Fps.WriteLn('i:=InterlockedDecrement(RefCnt);');
  1632. {$ifdef DEBUG}
  1633. Fps.WriteLn('writeln(''_TMethodPtrInfo.Release(). RefCnt='',i,'' ptr='',ptruint(Self));');
  1634. {$endif DEBUG}
  1635. Fps.WriteLn('if i <> 0 then exit;');
  1636. Fps.WriteLn('if Index > 0 then begin');
  1637. Fps.IncI;
  1638. Fps.WriteLn('_MethodPointersCS.Enter;');
  1639. Fps.WriteLn('try');
  1640. Fps.IncI;
  1641. Fps.WriteLn('if InlineHandler then begin');
  1642. Fps.IncI;
  1643. {$ifdef DEBUG}
  1644. Fps.WriteLn('writeln(''Finalizing Java inline handler.'');');
  1645. {$endif DEBUG}
  1646. Fps.WriteLn(Format('env^^.SetLongField(env, Obj, %s.ObjFieldId, -1);', [GetTypeInfoVar(d)]));
  1647. Fps.DecI;
  1648. Fps.WriteLn('end;');
  1649. Fps.WriteLn('env^^.DeleteGlobalRef(env, Obj);');
  1650. Fps.WriteLn('_MethodPointers[Index-1]:=nil;');
  1651. Fps.WriteLn('Index:=High(_MethodPointers);');
  1652. Fps.WriteLn('while (Index >= 0) and (_MethodPointers[Index] = nil) do Dec(Index);');
  1653. Fps.WriteLn('SetLength(_MethodPointers, Index + 1);');
  1654. Fps.WriteLn('finally', -1);
  1655. Fps.WriteLn('_MethodPointersCS.Leave;');
  1656. Fps.DecI;
  1657. Fps.WriteLn('end;');
  1658. Fps.DecI;
  1659. Fps.WriteLn('end;');
  1660. Fps.WriteLn('Self.Destroy;');
  1661. {$ifdef DEBUG}
  1662. Fps.WriteLn('writeln(''_TMethodPtrInfo destroyed.'');');
  1663. {$endif DEBUG}
  1664. Fps.DecI;
  1665. Fps.WriteLn('end;');
  1666. Fps.WriteLn;
  1667. Fps.WriteLn('procedure _RefMethodPtr(env: PJNIEnv; const m: TMethod; AddRef: boolean);');
  1668. Fps.WriteLn('var i: integer;');
  1669. Fps.WriteLn('begin');
  1670. Fps.IncI;
  1671. Fps.WriteLn('i:=-integer(ptruint(m.Data));');
  1672. {$ifdef DEBUG}
  1673. Fps.WriteLn('writeln(''_RefMethodPtr. i='',i,'' AddRef='',AddRef);');
  1674. {$endif DEBUG}
  1675. Fps.WriteLn(Format('if (i < 1) or (i > %d) then exit;', [MaxMethodPointers]));
  1676. Fps.WriteLn('_MethodPointersCS.Enter;');
  1677. Fps.WriteLn('try');
  1678. Fps.IncI;
  1679. Fps.WriteLn('with _MethodPointers[i - 1] do');
  1680. Fps.WriteLn('if AddRef then InterlockedIncrement(RefCnt) else Release(env);', 1);
  1681. Fps.WriteLn('finally', -1);
  1682. Fps.WriteLn('_MethodPointersCS.Leave;');
  1683. Fps.DecI;
  1684. Fps.WriteLn('end;');
  1685. Fps.DecI;
  1686. Fps.WriteLn('end;');
  1687. Fps.WriteLn;
  1688. Fps.WriteLn('function _CreateMethodPtrObject(env: PJNIEnv; const m: TMethod; const ci: _TJavaClassInfo): jobject;');
  1689. Fps.WriteLn('var i: integer;');
  1690. Fps.WriteLn('var mpi: _TMethodPtrInfo;');
  1691. Fps.WriteLn('begin');
  1692. Fps.IncI;
  1693. Fps.WriteLn('Result:=nil;');
  1694. Fps.WriteLn('if (m.Data = nil) and (m.Code = nil) then exit;');
  1695. Fps.WriteLn('_MethodPointersCS.Enter;');
  1696. Fps.WriteLn('try');
  1697. Fps.IncI;
  1698. Fps.WriteLn('i:=-integer(ptruint(m.Data));');
  1699. Fps.WriteLn(Format('if (i > 0) and (i <= %d) then begin', [MaxMethodPointers]));
  1700. Fps.WriteLn('mpi:=_MethodPointers[i - 1];', 1);
  1701. Fps.WriteLn('end');
  1702. Fps.WriteLn('else begin');
  1703. Fps.WriteLn('mpi:=_TMethodPtrInfo.Create(env, nil, '''', '''');', 1);
  1704. Fps.WriteLn('mpi.RealMethod:=m;', 1);
  1705. Fps.WriteLn('end;');
  1706. Fps.WriteLn('InterlockedIncrement(mpi.RefCnt);');
  1707. Fps.WriteLn('finally', -1);
  1708. Fps.WriteLn('_MethodPointersCS.Leave;');
  1709. Fps.DecI;
  1710. Fps.WriteLn('end;');
  1711. Fps.WriteLn('Result:=_CreateJavaObj(env, pointer(mpi), ci);');
  1712. Fps.DecI;
  1713. Fps.WriteLn('end;');
  1714. Fps.WriteLn;
  1715. Fps.WriteLn('function _GetMethodPtrHandler(env: PJNIEnv; jobj: jobject; hptr: pointer; const ci: _TJavaClassInfo): TMethod;');
  1716. Fps.WriteLn('var mpi: _TMethodPtrInfo;');
  1717. Fps.WriteLn('begin');
  1718. Fps.IncI;
  1719. Fps.WriteLn( 'Result.Data:=nil; Result.Code:=nil;');
  1720. Fps.WriteLn( 'mpi:=_TMethodPtrInfo(_GetPasObj(env, jobj, ci, False));');
  1721. Fps.WriteLn( 'if mpi = nil then exit;');
  1722. Fps.WriteLn( 'if pointer(mpi) = pointer(ptruint(-1)) then begin');
  1723. Fps.WriteLn( 'env^^.CallVoidMethodA(env, jobj, env^^.GetMethodID(env, ci.ClassRef, ''Init'', ''()V''), nil);', 1);
  1724. Fps.WriteLn( 'Result:=_GetMethodPtrHandler(env, jobj, hptr, ci);', 1);
  1725. Fps.WriteLn( 'exit;', 1);
  1726. Fps.WriteLn( 'end;');
  1727. Fps.WriteLn( 'if mpi.Index = 0 then');
  1728. Fps.WriteLn( 'TMethod(Result):=mpi.RealMethod', 1);
  1729. Fps.WriteLn( 'else');
  1730. Fps.WriteLn( 'with TMethod(Result) do begin', 1);
  1731. Fps.WriteLn( 'Data:=pointer(ptruint(-integer(mpi.Index)));', 2);
  1732. Fps.WriteLn( 'Code:=hptr;', 2);
  1733. Fps.WriteLn( 'end;', 1);
  1734. Fps.DecI;
  1735. Fps.WriteLn('end;');
  1736. Fps.WriteLn;
  1737. Fps.WriteLn('procedure _TMethodPtrInfo_Init(env: PJNIEnv; _self, JavaObj: JObject; AMethodName, AMethodSig: jstring; IncRef: jboolean);' + JniCaliing);
  1738. Fps.WriteLn('var mpi: _TMethodPtrInfo;');
  1739. Fps.WriteLn('begin');
  1740. Fps.IncI;
  1741. EHandlerStart;
  1742. Fps.WriteLn('mpi:=_TMethodPtrInfo.Create(env, JavaObj, ansistring(_StringFromJString(env, AMethodName)), ansistring(_StringFromJString(env, AMethodSig)));');
  1743. Fps.WriteLn('if IncRef <> 0 then');
  1744. Fps.WriteLn('InterlockedIncrement(mpi.RefCnt)', 1);
  1745. Fps.WriteLn('else');
  1746. Fps.WriteLn('mpi.InlineHandler:=True;', 1);
  1747. {$ifdef DEBUG}
  1748. Fps.WriteLn('writeln(''_TMethodPtrInfo_Init. RefCnt='',mpi.RefCnt,'' ptr='',ptruint(mpi));');
  1749. {$endif DEBUG}
  1750. Fps.WriteLn(Format('env^^.SetLongField(env, _self, %s.ObjFieldId, Int64(ptruint(mpi)));', [GetTypeInfoVar(d)]));
  1751. EHandlerEnd('env');
  1752. Fps.DecI;
  1753. Fps.WriteLn('end;');
  1754. AddNativeMethod(d, '_TMethodPtrInfo_Init', '__Init', Format('(Ljava/lang/Object;%s%sZ)V', [JNITypeSig[btString], JNITypeSig[btString]]));
  1755. Fps.WriteLn;
  1756. Fps.WriteLn('procedure _TMethodPtrInfo_Release(env: PJNIEnv; _self: JObject);' + JniCaliing);
  1757. Fps.WriteLn('begin');
  1758. Fps.IncI;
  1759. EHandlerStart;
  1760. Fps.WriteLn(Format('_TMethodPtrInfo(_GetPasObj(env, _self, %s, True)).Release(env);', [GetTypeInfoVar(d)]));
  1761. EHandlerEnd('env');
  1762. Fps.DecI;
  1763. Fps.WriteLn('end;');
  1764. AddNativeMethod(d, '_TMethodPtrInfo_Release', '__Destroy', '()V');
  1765. Fjs.WriteLn;
  1766. Fjs.WriteLn('public static class MethodPtr extends PascalObjectEx {');
  1767. Fjs.IncI;
  1768. Fjs.WriteLn('private native void __Init(Object Obj, String MethodName, String MethodSignature, boolean IncRef);');
  1769. Fjs.WriteLn('private native void __Destroy();');
  1770. Fjs.WriteLn('protected Object mObject;');
  1771. Fjs.WriteLn('protected String mName;');
  1772. Fjs.WriteLn('protected String mSignature;');
  1773. Fjs.WriteLn('protected void Init() { __Init(mObject, mName, mSignature, this != mObject); }');
  1774. Fjs.WriteLn('protected MethodPtr() { _cleanup=true; _pasobj=-1; }');
  1775. Fjs.WriteLn('public void __Release() { if (_pasobj > 0) __Destroy(); }');
  1776. Fjs.DecI;
  1777. Fjs.WriteLn('}');
  1778. Fjs.WriteLn;
  1779. // Base class for Enum
  1780. Fjs.WriteLn('public static class Enum {');
  1781. Fjs.IncI;
  1782. Fjs.WriteLn('public int Value;');
  1783. Fjs.WriteLn('public int Ord() { return Value; }');
  1784. Fjs.WriteLn('@Override public boolean equals(Object o) { return (o instanceof Integer) && Value == (Integer)o; }');
  1785. Fjs.WriteLn('public boolean equals(int v) { return Value == v; }');
  1786. Fjs.WriteLn('@Override public int hashCode() { return Value; }');
  1787. Fjs.DecI;
  1788. Fjs.WriteLn('}');
  1789. Fjs.WriteLn;
  1790. // Base class for Set
  1791. Fjs.WriteLn('private static abstract class BaseSet {');
  1792. Fjs.IncI;
  1793. Fjs.WriteLn('protected int Value = 0;');
  1794. Fjs.WriteLn('protected abstract byte Size();');
  1795. Fjs.WriteLn('protected abstract int Base();');
  1796. Fjs.WriteLn('protected abstract int ElMax();');
  1797. Fjs.WriteLn('public BaseSet() { }');
  1798. Fjs.DecI;
  1799. Fjs.WriteLn('}');
  1800. Fjs.WriteLn('public static abstract class Set<TS extends BaseSet,TE extends Enum> extends BaseSet {');
  1801. Fjs.IncI;
  1802. Fjs.WriteLn('protected int GetMask(TE Element) { return 1 << (Element.Ord() - Base()); }');
  1803. Fjs.WriteLn('public Set() { }');
  1804. Fjs.WriteLn('@SuppressWarnings({"unchecked", "varargs"})');
  1805. Fjs.WriteLn('public Set(TE... Elements) { Include(Elements); }');
  1806. Fjs.WriteLn('@SuppressWarnings({"unchecked", "varargs"})');
  1807. Fjs.WriteLn('public Set(TS... Elements) { for (TS e : Elements) Include(e); }');
  1808. Fjs.WriteLn('@SuppressWarnings({"unchecked", "varargs"})');
  1809. Fjs.WriteLn('public void Include(TE... Elements) { for (TE e: Elements) Value = Value | GetMask(e); }');
  1810. Fjs.WriteLn('public void Include(TS s) { Value=Value | s.Value; }');
  1811. Fjs.WriteLn('@SuppressWarnings({"unchecked", "varargs"})');
  1812. Fjs.WriteLn('public void Exclude(TE... Elements) { for (TE e: Elements) Value = Value & ~GetMask(e); }');
  1813. Fjs.WriteLn('public void Exclude(TS s) { Value=Value & ~s.Value; }');
  1814. Fjs.WriteLn('public void Assign(TS s) { Value=s.Value; }');
  1815. Fjs.WriteLn('public void Intersect(TS s) { Value=Value & s.Value; }');
  1816. Fjs.WriteLn('public boolean Has(TE Element) { return (Value & GetMask(Element)) != 0; }');
  1817. Fjs.WriteLn('public boolean IsEmpty() { return Value == 0; }');
  1818. Fjs.WriteLn('public boolean equals(TS s) { return Value == s.Value; }');
  1819. Fjs.WriteLn('public boolean equals(TE Element) { return Value == Element.Ord(); }');
  1820. Fjs.WriteLn('public boolean equals(int Element) { return Value == Element; }');
  1821. Fjs.DecI;
  1822. Fjs.WriteLn('}');
  1823. Fjs.WriteLn;
  1824. // TDateTime support
  1825. Fjs.WriteLn('public static class TDateTime {');
  1826. Fjs.IncI;
  1827. Fjs.WriteLn('public static Date toDateUTC(double d) {');
  1828. Fjs.WriteLn('return new Date(Math.round((d - 25569)*86400000.0));', 1);
  1829. Fjs.WriteLn('}');
  1830. Fjs.WriteLn('public static Date toDate(double d) {');
  1831. Fjs.WriteLn('long t = Math.round((d - 25569)*86400000.0); return new Date(t - TimeZone.getDefault().getOffset(t));', 1);
  1832. Fjs.WriteLn('}');
  1833. Fjs.WriteLn('public static double getUTC(Date d) {');
  1834. Fjs.WriteLn('return d.getTime()/86400000.0 + 25569;', 1);
  1835. Fjs.WriteLn('}');
  1836. Fjs.WriteLn('public static double get(Date d) {');
  1837. Fjs.WriteLn('return (d.getTime() + TimeZone.getDefault().getOffset(d.getTime()))/86400000.0 + 25569;', 1);
  1838. Fjs.WriteLn('}');
  1839. Fjs.DecI;
  1840. Fjs.WriteLn('}');
  1841. Fjs.WriteLn;
  1842. // Interface support
  1843. Fps.WriteLn;
  1844. Fps.WriteLn('function _IntfCast(env: PJNIEnv; _self: JObject; objptr: jlong; objid: jstring): jlong;' + JniCaliing);
  1845. Fps.WriteLn('var');
  1846. Fps.WriteLn('obj: system.TObject;', 1);
  1847. Fps.WriteLn('intf: IUnknown;', 1);
  1848. Fps.WriteLn('begin');
  1849. Fps.IncI;
  1850. Fps.WriteLn('Result:=0;');
  1851. EHandlerStart;
  1852. Fps.WriteLn('if objptr = 0 then exit;');
  1853. Fps.WriteLn('if objid = nil then');
  1854. Fps.WriteLn('raise Exception.Create(''A GUID must be assigned for the interface to allow a type cast.'');', 1);
  1855. Fps.WriteLn('obj:=system.TObject(pointer(ptruint(objptr)));');
  1856. Fps.WriteLn('if not (obj is system.TInterfacedObject) then');
  1857. Fps.WriteLn('raise Exception.Create(''Object must be inherited from TInterfacedObject.'');', 1);
  1858. Fps.WriteLn('if (system.TInterfacedObject(obj) as IUnknown).QueryInterface(StringToGUID(ansistring(_StringFromJString(env, objid))), intf) <> 0 then');
  1859. Fps.WriteLn('raise Exception.Create(''Invalid type cast.'');', 1);
  1860. Fps.WriteLn('intf._AddRef;');
  1861. Fps.WriteLn('Result:=ptruint(intf);');
  1862. EHandlerEnd('env');
  1863. Fps.DecI;
  1864. Fps.WriteLn('end;');
  1865. AddNativeMethod(u, '_IntfCast', 'InterfaceCast', '(JLjava/lang/String;)J');
  1866. Fjs.WriteLn('private native static long InterfaceCast(long objptr, String objid);');
  1867. Fjs.WriteLn;
  1868. Fjs.WriteLn('public static abstract class PascalInterface extends PascalObjectEx {');
  1869. Fjs.IncI;
  1870. Fjs.WriteLn('abstract protected void __Init();');
  1871. Fjs.WriteLn('public void __TypeCast(PascalObject obj, String intfId) {');
  1872. Fjs.WriteLn('if (obj != null) {', 1);
  1873. Fjs.WriteLn('if (obj instanceof PascalInterface) {', 2);
  1874. Fjs.WriteLn('_pasobj=obj._pasobj;',3);
  1875. Fjs.WriteLn('__Init();',3);
  1876. Fjs.WriteLn('} else',2);
  1877. Fjs.WriteLn('_pasobj=InterfaceCast(obj._pasobj, intfId);', 3);
  1878. Fjs.WriteLn('}', 1);
  1879. Fjs.WriteLn('}');
  1880. Fjs.WriteLn('protected PascalInterface(long objptr, boolean cleanup) { _pasobj=objptr; __Init(); }');
  1881. Fjs.DecI;
  1882. Fjs.WriteLn('}');
  1883. Fjs.WriteLn;
  1884. end;
  1885. if LibAutoLoad then begin
  1886. Fjs.WriteLn(Format('static { %s.system.InitJni(); }', [JavaPackage]));
  1887. Fjs.WriteLn;
  1888. end;
  1889. // First pass
  1890. for i:=0 to u.Count - 1 do begin
  1891. d:=u[i];
  1892. if not d.IsUsed then
  1893. continue;
  1894. case d.DefType of
  1895. dtSet, dtEnum:
  1896. WriteClassInfoVar(d);
  1897. dtClass:
  1898. WriteClass(TClassDef(d), True);
  1899. dtProcType:
  1900. WriteProcType(TProcDef(d), True);
  1901. dtPointer:
  1902. WritePointer(TPointerDef(d), True);
  1903. dtClassRef:
  1904. WriteClassRef(TClassRefDef(d), True);
  1905. end;
  1906. end;
  1907. // Second pass
  1908. for i:=0 to u.Count - 1 do begin
  1909. d:=u[i];
  1910. if not d.IsUsed then
  1911. continue;
  1912. case d.DefType of
  1913. dtClass:
  1914. WriteClass(TClassDef(d), False);
  1915. dtProc:
  1916. WriteProc(TProcDef(d));
  1917. dtVar, dtProp:
  1918. WriteVar(TVarDef(d));
  1919. dtEnum:
  1920. WriteEnum(d);
  1921. dtProcType:
  1922. WriteProcType(TProcDef(d), False);
  1923. dtSet:
  1924. WriteSet(TSetDef(d));
  1925. dtConst:
  1926. WriteConst(TConstDef(d));
  1927. dtPointer:
  1928. WritePointer(TPointerDef(d), False);
  1929. dtClassRef:
  1930. WriteClassRef(TClassRefDef(d), False);
  1931. end;
  1932. end;
  1933. // Class ref helpers
  1934. if (u.Name = 'system') and (FClasses.IndexOf('system.TClass', nil) >= 0) then begin
  1935. Fjs.WriteLn('native static long GetClassRef(int index);');
  1936. AddNativeMethod(u, '_GetClassRef', 'GetClassRef', '(I)J');
  1937. Fjs.WriteLn('static TClass GetTClass(int index) { TClass c = new TClass(null); c._pasobj=GetClassRef(index); return c; }');
  1938. Fjs.WriteLn;
  1939. end;
  1940. Fjs.DecI;
  1941. Fjs.WriteLn('}');
  1942. finally
  1943. Fjs.Free;
  1944. end;
  1945. end;
  1946. procedure TWriter.WriteOnLoad;
  1947. var
  1948. i, j: integer;
  1949. ci: TClassInfo;
  1950. s, ss, fn: string;
  1951. d: TTypeDef;
  1952. begin
  1953. if FClasses.Count = 0 then
  1954. exit;
  1955. Fps.WriteLn;
  1956. Fps.WriteLn('function JNI_OnLoad(vm: PJavaVM; reserved: pointer): jint;' + JniCaliing);
  1957. Fps.WriteLn('const');
  1958. for i:=0 to FClasses.Count - 1 do begin
  1959. ci:=FClasses.GetClassInfo(i);
  1960. if ci.Funcs.Count = 0 then
  1961. continue;
  1962. Fps.WriteLn(Format(' _%sNativeMethods: array[0..%d] of JNINativeMethod = (', [GetClassPrefix(ci.Def, FClasses.GetClassName(i)), ci.Funcs.Count - 1]));
  1963. for j:=0 to ci.Funcs.Count - 1 do begin
  1964. with TProcInfo(ci.Funcs[j]) do
  1965. Fps.Write(Format(' (name: ''%s''; signature: ''%s''; fnPtr: @%s)', [Name, JniSignature, JniName]));
  1966. if j < ci.Funcs.Count - 1 then
  1967. Fps.Write(',');
  1968. Fps.WriteLn;
  1969. end;
  1970. Fps.WriteLn(' );');
  1971. end;
  1972. Fps.WriteLn;
  1973. Fps.WriteLn('var');
  1974. Fps.IncI;
  1975. Fps.WriteLn('env: PJNIEnv;');
  1976. Fps.WriteLn;
  1977. Fps.WriteLn('function _Reg(ClassName: PAnsiChar; Methods: PJNINativeMethod; Count: integer; ci: _PJavaClassInfo; const FieldName: ansistring = ''_pasobj''; const FieldSig: ansistring = ''J''): boolean;');
  1978. Fps.WriteLn('var');
  1979. Fps.WriteLn('c: jclass;', 1);
  1980. Fps.WriteLn('begin');
  1981. Fps.IncI;
  1982. Fps.WriteLn('Result:=False;');
  1983. Fps.WriteLn('c:=env^^.FindClass(env, ClassName);');
  1984. Fps.WriteLn('if c = nil then exit;');
  1985. Fps.WriteLn('Result:=(Count = 0) or (env^^.RegisterNatives(env, c, Methods, Count) = 0);');
  1986. Fps.WriteLn('if Result and (ci <> nil) then begin');
  1987. Fps.IncI;
  1988. Fps.WriteLn('ci^.ClassRef:=env^^.NewGlobalRef(env, c);');
  1989. Fps.WriteLn('Result:=ci^.ClassRef <> nil;');
  1990. Fps.WriteLn('if Result and (env^^.ExceptionCheck(env) = 0) then begin');
  1991. Fps.WriteLn('ci^.ConstrId:=env^^.GetMethodID(env, ci^.ClassRef, ''<init>'', ''(JZ)V'');', 1);
  1992. Fps.WriteLn('env^^.ExceptionClear(env);', 1);
  1993. Fps.WriteLn('end;');
  1994. Fps.WriteLn('if Result and (FieldName <> '''') then begin');
  1995. Fps.WriteLn('ci^.ObjFieldId:=env^^.GetFieldID(env, ci^.ClassRef, PAnsiChar(FieldName), PAnsiChar(FieldSig));', 1);
  1996. Fps.WriteLn('Result:=ci^.ObjFieldId <> nil;', 1);
  1997. Fps.WriteLn('end;');
  1998. Fps.DecI;
  1999. Fps.WriteLn('end;');
  2000. Fps.DecI;
  2001. Fps.WriteLn('end;');
  2002. Fps.WriteLn;
  2003. Fps.WriteLn('begin', -1);
  2004. Fps.WriteLn('Result:=JNI_ERR;');
  2005. Fps.WriteLn('if vm^^.GetEnv(vm, @env, JNI_VERSION_1_6) <> JNI_OK then exit;');
  2006. Fps.WriteLn('CurJavaVM:=vm;');
  2007. d:=TTypeDef.Create(nil, dtType);
  2008. try
  2009. d.BasicType:=btString;
  2010. s:=JNITypeSig[d.BasicType];
  2011. s:=Copy(s, 2, Length(s) - 2);
  2012. Fps.WriteLn(Format('if not _Reg(''%s'', nil, 0, @%s, '''', '''') then exit;',
  2013. [s, GetTypeInfoVar(d)]));
  2014. finally
  2015. d.Free;
  2016. end;
  2017. for i:=0 to FClasses.Count - 1 do begin
  2018. ci:=FClasses.GetClassInfo(i);
  2019. s:=GetTypeInfoVar(ci.Def);
  2020. if (s = '') or (ci.IsCommonClass) then
  2021. s:='nil'
  2022. else
  2023. s:='@' + s;
  2024. if ci.Funcs.Count = 0 then
  2025. ss:='nil'
  2026. else
  2027. ss:=Format('@_%sNativeMethods', [GetClassPrefix(ci.Def, FClasses.GetClassName(i))]);
  2028. fn:='';
  2029. if ci.Def <> nil then
  2030. if ci.Def.DefType in [dtSet, dtEnum] then
  2031. fn:=', ''Value'', ''I''';
  2032. Fps.WriteLn(Format('if not _Reg(''%s'', %s, %d, %s%s) then exit;',
  2033. [GetJavaClassPath(ci.Def, FClasses.GetClassName(i)), ss, ci.Funcs.Count, s, fn]));
  2034. end;
  2035. Fps.WriteLn('Result:=JNI_VERSION_1_6;');
  2036. Fps.DecI;
  2037. Fps.WriteLn('end;');
  2038. Fps.WriteLn;
  2039. Fps.WriteLn('exports JNI_OnLoad;');
  2040. end;
  2041. procedure TWriter.WriteRecordSizes;
  2042. var
  2043. i, j: integer;
  2044. s: string;
  2045. begin
  2046. Fps.WriteLn;
  2047. Fps.WriteLn('function _GetRecordSize(env: PJNIEnv; jobj: jobject; index: jint): jint;' + JniCaliing);
  2048. if FRecords.Count > 0 then begin
  2049. Fps.WriteLn(Format('const sizes: array[0..%d] of longint =', [FRecords.Count - 1]));
  2050. Fps.IncI;
  2051. s:='(';
  2052. j:=0;
  2053. for i:=0 to FRecords.Count - 1 do begin
  2054. if i > 0 then
  2055. s:=s + ',';
  2056. Inc(j);
  2057. if j > 20 then begin
  2058. Fps.WriteLn(s);
  2059. s:='';
  2060. j:=0;
  2061. end;
  2062. s:=s + IntToStr(TClassDef(FRecords[i]).Size);
  2063. end;
  2064. Fps.WriteLn(s + ');');
  2065. Fps.DecI;
  2066. end;
  2067. Fps.WriteLn('begin');
  2068. if FRecords.Count > 0 then
  2069. s:='sizes[index]'
  2070. else
  2071. s:='0';
  2072. Fps.WriteLn('Result:=' + s + ';', 1);
  2073. Fps.WriteLn('end;');
  2074. end;
  2075. procedure TWriter.WriteClassTable;
  2076. var
  2077. i: integer;
  2078. s,ss: string;
  2079. begin
  2080. Fps.WriteLn;
  2081. Fps.WriteLn('function _GetClassRef(env: PJNIEnv; jobj: jobject; index: jint): jlong;' + JniCaliing);
  2082. if FRealClasses.Count > 0 then begin
  2083. Fps.WriteLn(Format('const cls: array[0..%d] of TClass =', [FRealClasses.Count - 1]));
  2084. Fps.IncI;
  2085. s:='(';
  2086. for i:=0 to FRealClasses.Count - 1 do begin
  2087. if i > 0 then
  2088. s:=s + ',';
  2089. if Length(s) > 100 then begin
  2090. Fps.WriteLn(s);
  2091. s:='';
  2092. end;
  2093. with TClassDef(FRealClasses[i]) do
  2094. ss:=Parent.Name + '.' + Name;
  2095. s:=s + ss;
  2096. end;
  2097. Fps.WriteLn(s + ');');
  2098. Fps.DecI;
  2099. end;
  2100. Fps.WriteLn('begin');
  2101. if FRealClasses.Count > 0 then
  2102. s:='cls[index]'
  2103. else
  2104. s:='nil';
  2105. Fps.WriteLn('Result:=-jlong(ptruint(pointer(' + s + ')));', 1);
  2106. Fps.WriteLn('end;');
  2107. end;
  2108. function TWriter.JniToPasType(d: TDef; const v: string; CheckNil: boolean): string;
  2109. var
  2110. n: string;
  2111. begin
  2112. Result:=v;
  2113. if d = nil then
  2114. exit;
  2115. case d.DefType of
  2116. dtType:
  2117. with TTypeDef(d) do
  2118. case BasicType of
  2119. btString, btWideString:
  2120. begin
  2121. Result:=Format('_StringFromJString(_env, %s)', [Result]);
  2122. if BasicType <> btWideString then
  2123. Result:=Format('%s(%s)', [d.Name, Result]);
  2124. end;
  2125. btBoolean:
  2126. Result:=Format('LongBool(%s)', [Result]);
  2127. btChar:
  2128. Result:=Format('char(widechar(%s))', [Result]);
  2129. btWideChar:
  2130. Result:=Format('widechar(%s)', [Result]);
  2131. btGuid:
  2132. Result:=Format('StringToGUID(ansistring(_StringFromJString(_env, %s)))', [Result]);
  2133. else
  2134. Result:=Format('%s.%s(%s)', [d.Parent.Name, d.Name, Result]);
  2135. end;
  2136. dtClass:
  2137. begin
  2138. if TClassDef(d).CType = ctRecord then
  2139. n:='True'
  2140. else
  2141. if CheckNil then
  2142. n:='True'
  2143. else
  2144. n:='False';
  2145. Result:=Format('_GetPasObj(_env, %s, %s, %s)', [Result, GetTypeInfoVar(d), n]);
  2146. if TClassDef(d).CType in [ctObject, ctRecord] then
  2147. Result:=Result + '^';
  2148. Result:=Format('%s.%s(%s)', [d.Parent.Name, d.Name, Result]);
  2149. end;
  2150. dtProcType:
  2151. Result:=Format('%sGetHandler(_env, %s, %s)', [GetClassPrefix(d), Result, GetTypeInfoVar(d)]);
  2152. dtEnum:
  2153. Result:=Format('%s.%s(_GetIntObjValue(_env, %s, %s))', [d.Parent.Name, d.Name, Result, GetTypeInfoVar(d)]);
  2154. dtSet:
  2155. Result:=Format('%s.%s(%s(_GetIntObjValue(_env, %s, %s)))', [d.Parent.Name, d.Name, GetPasIntType(TSetDef(d).Size), Result, GetTypeInfoVar(d)]);
  2156. dtPointer:
  2157. begin
  2158. if TPointerDef(d).IsObjPtr then
  2159. Result:=Format('%s.%s(_GetPasObj(_env, %s, %s, False))', [d.Parent.Name, d.Name, Result, GetTypeInfoVar(d)])
  2160. else
  2161. Result:=Format('pointer(ptruint(%s))', [Result]);
  2162. end;
  2163. dtClassRef:
  2164. begin
  2165. Result:=Format('_GetClass(_env, %s, %s)', [Result, GetTypeInfoVar(d)]);
  2166. Result:=Format('%s.%s(%s)', [d.Parent.Name, d.Name, Result]);
  2167. end;
  2168. end;
  2169. end;
  2170. function TWriter.PasToJniType(d: TDef; const v: string): string;
  2171. begin
  2172. Result:=v;
  2173. if d = nil then
  2174. exit;
  2175. case d.DefType of
  2176. dtType:
  2177. with TTypeDef(d) do
  2178. case BasicType of
  2179. btString, btWideString:
  2180. Result:=Format('_StringToJString(_env, _JNIString(%s))', [Result]);
  2181. btBoolean:
  2182. Result:=Format('(jboolean(%s) and 1)', [Result]);
  2183. btChar:
  2184. Result:=Format('jchar(widechar(%s))', [Result]);
  2185. btWideChar:
  2186. Result:=Format('jchar(%s)', [Result]);
  2187. btEnum:
  2188. Result:=Format('jint(%s)', [Result]);
  2189. btGuid:
  2190. Result:=Format('_StringToJString(_env, _JNIString(GUIDToString(%s)))', [Result]);
  2191. end;
  2192. dtClass:
  2193. case TClassDef(d).CType of
  2194. ctObject, ctRecord:
  2195. Result:=Format('_%s_CreateObj(_env, %s)', [GetClassPrefix(d), Result]);
  2196. ctInterface:
  2197. Result:=Format('_CreateJavaObj(_env, pointer(%s), %s)', [Result, GetTypeInfoVar(d)]);
  2198. else
  2199. Result:=Format('_CreateJavaObj(_env, %s, %s)', [Result, GetTypeInfoVar(d)]);
  2200. end;
  2201. dtProcType:
  2202. Result:=Format('_CreateMethodPtrObject(_env, TMethod(%s), %s)', [Result, GetTypeInfoVar(d)]);
  2203. dtEnum:
  2204. Result:=Format('_CreateIntObj(_env, longint(%s), %s)', [Result, GetTypeInfoVar(d)]);
  2205. dtSet:
  2206. Result:=Format('_CreateIntObj(_env, %s(%s), %s)', [GetPasIntType(TSetDef(d).Size), Result, GetTypeInfoVar(d)]);
  2207. dtPointer:
  2208. if TPointerDef(d).IsObjPtr then
  2209. Result:=Format('_CreateJavaObj(_env, %s, %s)', [Result, GetTypeInfoVar(d)])
  2210. else
  2211. Result:=Format('ptruint(pointer(%s))', [Result]);
  2212. dtClassRef:
  2213. Result:=Format('_CreateJavaObj(_env, -jlong(ptruint(pointer(%s))), %s)', [Result, GetTypeInfoVar(d)])
  2214. end;
  2215. end;
  2216. function TWriter.GetTypeInfoVar(ClassDef: TDef): string;
  2217. begin
  2218. if ClassDef.DefType = dtUnit then
  2219. Result:=''
  2220. else
  2221. if ClassDef.DefType = dtType then
  2222. Result:='_Java_' + JavaType[TTypeDef(ClassDef).BasicType] + '_Info'
  2223. else
  2224. Result:='_JNI_' + ClassDef.Parent.Name + '_' + ClassDef.Name + '_Info';
  2225. end;
  2226. function TWriter.GetClassPrefix(ClassDef: TDef; const AClassName: string): string;
  2227. begin
  2228. if AClassName = '' then
  2229. Result:=ClassDef.Name
  2230. else
  2231. Result:=AClassName;
  2232. Result:=Result + '_';
  2233. if ClassDef.DefType <> dtUnit then
  2234. Result:=ClassDef.Parent.Name + '_' + Result;
  2235. Result:='JNI_' + Result;
  2236. end;
  2237. function TWriter.IsJavaSimpleType(d: TDef): boolean;
  2238. begin
  2239. Result:=d <> nil;
  2240. if Result then
  2241. case d.DefType of
  2242. dtType:
  2243. Result:=Length(JNITypeSig[TTypeDef(d).BasicType]) = 1;
  2244. dtPointer:
  2245. Result:=not TPointerDef(d).IsObjPtr;
  2246. else
  2247. Result:=False;
  2248. end;
  2249. end;
  2250. function TWriter.IsJavaVarParam(ParamDef: TVarDef): boolean;
  2251. begin
  2252. with ParamDef do
  2253. Result:=VarOpt * [voVar, voOut] <> [];
  2254. end;
  2255. function TWriter.GetProcDeclaration(d: TProcDef; const ProcName: string; FullTypeNames: boolean; InternalParaNames: boolean): string;
  2256. var
  2257. s, ss: string;
  2258. j: integer;
  2259. begin
  2260. with d do begin
  2261. s:='';
  2262. for j:=0 to Count - 1 do
  2263. with TVarDef(Items[j]) do begin
  2264. if DefType <> dtParam then
  2265. continue;
  2266. if s <> '' then
  2267. s:=s + '; ';
  2268. if voVar in VarOpt then
  2269. s:=s + 'var '
  2270. else
  2271. if voOut in VarOpt then
  2272. s:=s + 'out '
  2273. else
  2274. if voConst in VarOpt then
  2275. s:=s + 'const ';
  2276. if InternalParaNames then
  2277. s:=s + Name
  2278. else
  2279. s:=s + AliasName;
  2280. s:=s + ': ' + GetPasType(VarType, FullTypeNames);
  2281. end;
  2282. if s <> '' then
  2283. s:='(' + s + ')';
  2284. case ProcType of
  2285. ptConstructor:
  2286. ss:='constructor';
  2287. ptDestructor:
  2288. ss:='destructor';
  2289. ptProcedure:
  2290. ss:='procedure';
  2291. ptFunction:
  2292. ss:='function';
  2293. else
  2294. ss:='';
  2295. end;
  2296. if ProcType in [ptConstructor, ptFunction] then
  2297. s:=s + ': ' + GetPasType(ReturnType, FullTypeNames);
  2298. ss:=ss + ' ';
  2299. if ProcName <> '' then
  2300. ss:=ss + ProcName
  2301. else
  2302. ss:=ss + Name;
  2303. Result:=ss + s;
  2304. end;
  2305. end;
  2306. function TWriter.GetJavaProcDeclaration(d: TProcDef; const ProcName: string): string;
  2307. var
  2308. s, ss: string;
  2309. j: integer;
  2310. vd: TVarDef;
  2311. begin
  2312. with d do begin
  2313. if ProcName <> '' then
  2314. ss:=ProcName
  2315. else
  2316. ss:=AliasName;
  2317. ss:=DefToJavaType(ReturnType) + ' ' + ss + '(';
  2318. s:='';
  2319. for j:=0 to Count - 1 do begin
  2320. vd:=TVarDef(Items[j]);
  2321. if vd.DefType <> dtParam then
  2322. continue;
  2323. with vd do begin
  2324. if (VarType <> nil) and (VarType.DefType = dtJniEnv) then
  2325. continue;
  2326. if s <> '' then
  2327. s:=s + ', ';
  2328. s:=s + DefToJavaType(VarType);
  2329. if IsJavaVarParam(vd) then
  2330. s:=s + '[]';
  2331. s:=s + ' ' + AliasName;
  2332. end;
  2333. end;
  2334. ss:=ss + s + ')';
  2335. end;
  2336. Result:=ss;
  2337. end;
  2338. function TWriter.GetJniFuncType(d: TDef): string;
  2339. begin
  2340. if IsJavaSimpleType(d) then begin
  2341. if d.DefType = dtPointer then
  2342. Result:='Long'
  2343. else begin
  2344. Result:=JavaType[TTypeDef(d).BasicType];
  2345. Result[1]:=UpCase(Result[1]);
  2346. end;
  2347. end
  2348. else
  2349. Result:='Object';
  2350. end;
  2351. function TWriter.GetJavaClassName(cls: TDef; it: TDef): string;
  2352. begin
  2353. Result:=cls.AliasName;
  2354. if (cls.DefType <> dtClass) or ((it <> nil) and not (it.DefType in ReplDefs)) then
  2355. exit;
  2356. with TClassDef(cls) do begin
  2357. if not (HasReplacedItems or ImplementsReplacedItems) then
  2358. exit;
  2359. if ImplementsReplacedItems and not HasReplacedItems then
  2360. exit;
  2361. if it <> nil then
  2362. with TReplDef(it) do begin
  2363. if (it.DefType = dtProc) and (TProcDef(it).ProcType = ptConstructor) then
  2364. exit;
  2365. if IsReplaced or IsReplImpl then
  2366. exit;
  2367. end;
  2368. end;
  2369. Result:='__' + Result;
  2370. end;
  2371. procedure TWriter.RegisterPseudoClass(d: TDef);
  2372. var
  2373. ci: TClassInfo;
  2374. begin
  2375. if FClasses.IndexOf(d.Name, d) < 0 then begin
  2376. ci:=TClassInfo.Create;
  2377. ci.Def:=d;
  2378. FClasses.Add(d.Name, d, ci);
  2379. end;
  2380. end;
  2381. function TWriter.GetPasIntType(Size: integer): string;
  2382. begin
  2383. case Size of
  2384. 1: Result:='byte';
  2385. 2: Result:='word';
  2386. else
  2387. Result:='cardinal';
  2388. end;
  2389. end;
  2390. function TWriter.GetPasType(d: TDef; FullName: boolean): string;
  2391. begin
  2392. Result:=d.Name;
  2393. if FullName and (d.DefType <> dtType) then
  2394. Result:=d.Parent.Name + '.' + Result;
  2395. end;
  2396. function TWriter.AddCustomProc(ParentDef: TDef; const JniName, Name: string; RetType: TBasicType; const Params: array of TBasicType): TProcDef;
  2397. var
  2398. i: integer;
  2399. vd: TVarDef;
  2400. begin
  2401. Result:=TProcDef.Create(ParentDef, dtProc);
  2402. Result.Name:=JniName;
  2403. Result.AliasName:=Name;
  2404. if RetType = btVoid then
  2405. Result.ProcType:=ptProcedure
  2406. else
  2407. Result.ProcType:=ptFunction;
  2408. for i:=0 to High(Params) do begin
  2409. vd:=TVarDef.Create(Result, dtParam);
  2410. vd.Name:=Format('p%d', [i + 1]);
  2411. vd.VarType:=TTypeDef.Create(vd, dtType);
  2412. TTypeDef(vd.VarType).BasicType:=Params[i];
  2413. end;
  2414. Result.ReturnType:=TTypeDef.Create(ParentDef, dtType);
  2415. TTypeDef(Result.ReturnType).BasicType:=RetType;
  2416. end;
  2417. procedure TWriter.AddNativeMethod(ParentDef: TDef; const JniName, Name, Signature: string);
  2418. var
  2419. i: integer;
  2420. ci: TClassInfo;
  2421. pi: TProcInfo;
  2422. begin
  2423. pi:=TProcInfo.Create;
  2424. pi.Name:=Name;
  2425. pi.JniName:=JniName;
  2426. pi.JniSignature:=Signature;
  2427. i:=FClasses.IndexOf(ParentDef.AliasName, ParentDef);
  2428. if i < 0 then begin
  2429. ci:=TClassInfo.Create;
  2430. ci.Def:=ParentDef;
  2431. i:=FClasses.Add(ParentDef.AliasName, ParentDef, ci);
  2432. end;
  2433. FClasses.GetClassInfo(i).Funcs.Add(pi);
  2434. end;
  2435. function TWriter.GetProcSignature(d: TProcDef): string;
  2436. var
  2437. j: integer;
  2438. vd: TVarDef;
  2439. begin
  2440. Result:='(';
  2441. for j:=0 to d.Count - 1 do begin
  2442. vd:=TVarDef(d[j]);
  2443. if vd.DefType <> dtParam then
  2444. continue;
  2445. with vd do begin
  2446. if (VarType <> nil) and (VarType.DefType = dtJniEnv) then
  2447. continue;
  2448. if IsJavaVarParam(vd) then
  2449. Result:=Result + '[';
  2450. Result:=Result + DefToJniSig(VarType);
  2451. end;
  2452. end;
  2453. Result:=Result + ')' + DefToJniSig(d.ReturnType);
  2454. end;
  2455. procedure TWriter.EHandlerStart;
  2456. begin
  2457. Fps.WriteLn('try');
  2458. Fps.IncI;
  2459. end;
  2460. procedure TWriter.EHandlerEnd(const EnvVarName: string; const ExtraCode: string);
  2461. begin
  2462. Fps.WriteLn('except', -1);
  2463. Fps.WriteLn(Format('_HandleJNIException(%s);', [EnvVarName]));
  2464. if ExtraCode <> '' then
  2465. Fps.WriteLn(ExtraCode);
  2466. Fps.DecI;
  2467. Fps.WriteLn('end;');
  2468. end;
  2469. procedure TWriter.UpdateUsedUnits(u: TUnitDef);
  2470. procedure _CheckDef(d: TDef);
  2471. begin
  2472. if (d = nil) or not d.IsUsed then
  2473. exit;
  2474. d:=d.Parent;
  2475. if (d <> nil) and (d.DefType = dtUnit) then
  2476. with TUnitDef(d) do
  2477. if not IsUnitUsed and IsUsed then
  2478. IsUnitUsed:=True;
  2479. end;
  2480. procedure _ScanDef(def: TDef);
  2481. var
  2482. i: integer;
  2483. d: TDef;
  2484. begin
  2485. for i:=0 to def.Count - 1 do begin
  2486. d:=def[i];
  2487. if not d.IsUsed then
  2488. continue;
  2489. _CheckDef(d.GetRefDef);
  2490. _CheckDef(d.GetRefDef2);
  2491. _ScanDef(d);
  2492. end;
  2493. end;
  2494. var
  2495. i: integer;
  2496. begin
  2497. for i:=0 to High(u.UsedUnits) do
  2498. u.UsedUnits[i].IsUnitUsed:=False;
  2499. _ScanDef(u);
  2500. end;
  2501. procedure TWriter.WriteClassInfoVar(d: TDef);
  2502. begin
  2503. Fps.WriteLn;
  2504. Fps.WriteLn(Format('var %s: _TJavaClassInfo;', [GetTypeInfoVar(d)]));
  2505. end;
  2506. procedure TWriter.WriteComment(d: TDef; const AType: string);
  2507. begin
  2508. Fps.WriteLn;
  2509. Fps.WriteLn(Format('{ %s }', [d.Name]));
  2510. Fjs.WriteLn(Format('/* %s */', [Trim(AType + ' ' + d.Name)]));
  2511. {$ifdef DEBUG}
  2512. Fjs.WriteLn(Format('/* Ref count: %d */', [d.RefCnt]));
  2513. {$endif}
  2514. end;
  2515. {
  2516. procedure TWriter.AddCustomProc(ParentDef: TDef; const JniName, Name: string; RetType: TBasicType; const Params: array of TBasicType);
  2517. var
  2518. i: integer;
  2519. ci: TClassInfo;
  2520. pi: TProcInfo;
  2521. begin
  2522. pi:=TProcInfo.Create;
  2523. pi.Name:=Name;
  2524. pi.JniName:=JniName;
  2525. pi.JniSignature:='(';
  2526. for i:=0 to High(Params) do
  2527. pi.JniSignature:=pi.JniSignature + JNITypeSig[Params[i]];
  2528. pi.JniSignature:=pi.JniSignature + ')';
  2529. pi.JniSignature:=pi.JniSignature + JNITypeSig[RetType];
  2530. i:=FClasses.IndexOf(ParentDef.Name);
  2531. if i < 0 then begin
  2532. ci:=TClassInfo.Create;
  2533. ci.Def:=ParentDef;
  2534. i:=FClasses.AddObject(ParentDef.Name, ci);
  2535. end;
  2536. TClassInfo(FClasses.Objects[i]).Funcs.Add(pi);
  2537. end;
  2538. }
  2539. constructor TWriter.Create;
  2540. var
  2541. i: integer;
  2542. begin
  2543. Units:=TStringList.Create;
  2544. FClasses:=TClassList.Create;
  2545. JavaPackage:='pas';
  2546. IncludeList:=TStringList.Create;
  2547. IncludeList.Duplicates:=dupIgnore;
  2548. ExcludeList:=TStringList.Create;
  2549. ExcludeList.Duplicates:=dupIgnore;
  2550. for i:=Low(ExcludeStd) to High(ExcludeStd) do
  2551. ExcludeList.Add(ExcludeStd[i]);
  2552. for i:=Low(ExcludeDelphi7) to High(ExcludeDelphi7) do
  2553. ExcludeList.Add(ExcludeDelphi7[i]);
  2554. FThisUnit:=TUnitDef.Create(nil, dtUnit);
  2555. FRecords:=TObjectList.Create(False);
  2556. FRealClasses:=TObjectList.Create(False);
  2557. LibAutoLoad:=True;
  2558. end;
  2559. function DoCanUseDef(def, refdef: TDef): boolean;
  2560. begin
  2561. Result:=True;
  2562. if (def.DefType = dtArray) and (refdef is TVarDef) then begin
  2563. // Arrays are supported only for variables, fields, properties and constants
  2564. Result:=refdef.DefType in [dtVar, dtProp, dtField, dtConst];
  2565. end;
  2566. end;
  2567. destructor TWriter.Destroy;
  2568. var
  2569. i: integer;
  2570. begin
  2571. for i:=0 to FClasses.Count - 1 do
  2572. FClasses.Objects[i].Free;
  2573. FClasses.Free;
  2574. Units.Free;
  2575. IncludeList.Free;
  2576. ExcludeList.Free;
  2577. FThisUnit.Free;
  2578. FRecords.Free;
  2579. FRealClasses.Free;
  2580. inherited Destroy;
  2581. end;
  2582. procedure TWriter.ProcessUnits;
  2583. procedure _ExcludeClasses(u: TDef; AAncestorClass: TClassDef);
  2584. var
  2585. i: integer;
  2586. d: TDef;
  2587. s: string;
  2588. excl: boolean;
  2589. begin
  2590. for i:=0 to u.Count - 1 do begin
  2591. d:=u[i];
  2592. if d.DefType = dtClass then begin
  2593. s:=u.Name + '.' + d.Name;
  2594. if AAncestorClass = nil then begin
  2595. excl:=DoCheckItem(s) = crExclude;
  2596. if not excl and (TClassDef(d).AncestorClass <> nil) then
  2597. with TClassDef(d).AncestorClass do
  2598. excl:=DoCheckItem(Parent.Name + '.' + Name) = crExclude;
  2599. end
  2600. else
  2601. excl:=TClassDef(d).AncestorClass = AAncestorClass;
  2602. if excl then begin
  2603. d.SetNotUsed;
  2604. ExcludeList.Add(s);
  2605. _ExcludeClasses(u, TClassDef(d));
  2606. end;
  2607. end;
  2608. end;
  2609. end;
  2610. var
  2611. p: TPPUParser;
  2612. i: integer;
  2613. s, ss: string;
  2614. d: TDef;
  2615. begin
  2616. if Units.Count = 0 then
  2617. raise Exception.Create('No unit name specified.');
  2618. if (OutPath <> '') and not DirectoryExists(OutPath) then
  2619. raise Exception.CreateFmt('Output path "%s" does not exist.', [OutPath]);
  2620. if (JavaOutPath <> '') and not DirectoryExists(JavaOutPath) then
  2621. raise Exception.CreateFmt('Output path "%s" does not exist.', [JavaOutPath]);
  2622. if LibName = '' then
  2623. LibName:=AnsiLowerCase(ChangeFileExt(Units[0], '')) + 'jni';
  2624. for i:=0 to IncludeList.Count - 1 do
  2625. IncludeList[i]:=Trim(IncludeList[i]);
  2626. IncludeList.Sorted:=True;
  2627. for i:=0 to ExcludeList.Count - 1 do
  2628. ExcludeList[i]:=Trim(ExcludeList[i]);
  2629. ExcludeList.Sorted:=True;
  2630. FThisUnit.Name:=LibName;
  2631. FThisUnit.AliasName:='system';
  2632. p:=TPPUParser.Create(SearchPath);
  2633. try
  2634. p.OnCheckItem:=@DoCheckItem;
  2635. OnCanUseDef:=@DoCanUseDef;
  2636. for i:=0 to Units.Count - 1 do
  2637. IncludeList.Add(ChangeFileExt(ExtractFileName(Units[i]), ''));
  2638. for i:=0 to Units.Count - 1 do
  2639. p.Parse(ChangeFileExt(ExtractFileName(Units[i]), ''));
  2640. if OutPath <> '' then
  2641. OutPath:=IncludeTrailingPathDelimiter(OutPath);
  2642. if JavaOutPath <> '' then
  2643. JavaOutPath:=IncludeTrailingPathDelimiter(JavaOutPath);
  2644. FPkgDir:=JavaOutPath + StringReplace(JavaPackage, '.', DirectorySeparator, [rfReplaceAll]);
  2645. ForceDirectories(FPkgDir);
  2646. Fps:=TTextOutStream.Create(OutPath + LibName + '.pas', fmCreate);
  2647. WriteFileComment(Fps);
  2648. Fps.WriteLn('library '+ LibName + ';');
  2649. Fps.WriteLn('{$ifdef fpc} {$mode objfpc} {$H+} {$endif}');
  2650. Fps.WriteLn;
  2651. Fps.WriteLn('uses');
  2652. Fps.WriteLn('{$ifdef unix} cthreads, {$endif}', 1);
  2653. s:='';
  2654. for i:=0 to p.Units.Count - 1 do begin
  2655. ProcessRules(p.Units[i]);
  2656. ss:=LowerCase(p.Units[i].Name);
  2657. if (ss ='system') or (ss = 'objpas') or (ss = 'sysutils') or (ss = 'syncobjs') or (ss = 'jni')
  2658. or (ss = 'cthreads') or (ss = 'windows')
  2659. then
  2660. continue;
  2661. if s <> '' then
  2662. s:=s + ', ';
  2663. if Length(s) >= 100 then begin
  2664. Fps.WriteLn(s, 1);
  2665. s:='';
  2666. end;
  2667. s:=s + p.Units[i].Name;
  2668. end;
  2669. if s <> '' then
  2670. Fps.WriteLn(s + ',', 1);
  2671. Fps.WriteLn('{$ifndef FPC} Windows, {$endif} SysUtils, SyncObjs, jni;', 1);
  2672. // Types
  2673. Fps.WriteLn;
  2674. Fps.WriteLn('type');
  2675. Fps.IncI;
  2676. Fps.WriteLn('_JNIString = {$ifdef FPC} unicodestring {$else} widestring {$endif};');
  2677. Fps.WriteLn('{$ifndef FPC} ptruint = cardinal; {$endif}');
  2678. Fps.WriteLn;
  2679. Fps.WriteLn('_TJavaClassInfo = record');
  2680. Fps.WriteLn('ClassRef: JClass;', 1);
  2681. Fps.WriteLn('ConstrId: JMethodId;', 1);
  2682. Fps.WriteLn('ObjFieldId: JFieldId;', 1);
  2683. Fps.WriteLn('end;');
  2684. Fps.WriteLn('_PJavaClassInfo = ^_TJavaClassInfo;');
  2685. Fps.DecI;
  2686. Fps.WriteLn;
  2687. d:=TtypeDef.Create(nil, dtType);
  2688. TtypeDef(d).BasicType:=btString;
  2689. Fps.WriteLn(Format('var %s: _TJavaClassInfo;', [GetTypeInfoVar(d)]));
  2690. d.Free;
  2691. // Support functions
  2692. Fps.WriteLn;
  2693. Fps.WriteLn('function _StringFromJString(env: PJNIEnv; s: jstring): _JNIString;');
  2694. Fps.WriteLn('var');
  2695. Fps.WriteLn('p: PJChar;', 1);
  2696. Fps.WriteLn('c: JBoolean;', 1);
  2697. Fps.WriteLn('begin');
  2698. Fps.WriteLn('if s = nil then begin', 1);
  2699. Fps.WriteLn('Result:='''';', 2);
  2700. Fps.WriteLn('exit;', 2);
  2701. Fps.WriteLn('end;', 1);
  2702. Fps.WriteLn('p:=env^^.GetStringChars(env, s, c);', 1);
  2703. Fps.WriteLn('SetString(Result, PWideChar(p), env^^.GetStringLength(env, s));', 1);
  2704. Fps.WriteLn('env^^.ReleaseStringChars(env, s, p);', 1);
  2705. Fps.WriteLn('end;');
  2706. Fps.WriteLn;
  2707. Fps.WriteLn('function _StringToJString(env: PJNIEnv; const s: _JNIString): jstring;');
  2708. Fps.WriteLn('begin');
  2709. Fps.WriteLn('Result:=env^^.NewString(env, PJChar(PWideChar(s)), Length(s));', 1);
  2710. Fps.WriteLn('end;');
  2711. Fps.WriteLn;
  2712. Fps.WriteLn('function _CreateJavaObj(env: PJNIEnv; PasObj: jlong; const ci: _TJavaClassInfo; cleanup: boolean = True): jobject; overload;');
  2713. Fps.WriteLn('var v: array [0..1] of jvalue;');
  2714. Fps.WriteLn('begin');
  2715. Fps.IncI;
  2716. Fps.WriteLn('Result:=nil;');
  2717. Fps.WriteLn('if PasObj = 0 then exit;');
  2718. Fps.WriteLn('v[0].J:=PasObj;');
  2719. Fps.WriteLn('if ci.ConstrId = nil then begin');
  2720. Fps.WriteLn('Result:=env^^.AllocObject(env, ci.ClassRef);', 1);
  2721. Fps.WriteLn('if Result = nil then exit;', 1);
  2722. Fps.WriteLn('env^^.SetLongField(env, Result, ci.ObjFieldId, v[0].J);', 1);
  2723. Fps.WriteLn('end else begin');
  2724. Fps.WriteLn('v[1].Z:=byte(cleanup) and 1;', 1);
  2725. Fps.WriteLn('Result:=env^^.NewObjectA(env, ci.ClassRef, ci.ConstrId, @v);', 1);
  2726. Fps.WriteLn('end;');
  2727. Fps.DecI;
  2728. Fps.WriteLn('end;');
  2729. Fps.WriteLn;
  2730. Fps.WriteLn('function _CreateJavaObj(env: PJNIEnv; PasObj: pointer; const ci: _TJavaClassInfo; cleanup: boolean = True): jobject; overload;');
  2731. Fps.WriteLn('begin');
  2732. Fps.WriteLn('Result:=_CreateJavaObj(env, jlong(ptruint(PasObj)), ci, cleanup)', 1);
  2733. Fps.WriteLn('end;');
  2734. Fps.WriteLn;
  2735. Fps.WriteLn('function _GetPasObj(env: PJNIEnv; jobj: jobject; const ci: _TJavaClassInfo; CheckNil: boolean): pointer;');
  2736. Fps.WriteLn('var pasobj: jlong;');
  2737. Fps.WriteLn('begin');
  2738. Fps.IncI;
  2739. Fps.WriteLn('if jobj <> nil then');
  2740. Fps.WriteLn('pasobj:=env^^.GetLongField(env, jobj, ci.ObjFieldId)', 1);
  2741. Fps.WriteLn('else');
  2742. Fps.WriteLn('pasobj:=0;', 1);
  2743. Fps.WriteLn('if CheckNil and (pasobj <= 0) then');
  2744. Fps.WriteLn('raise Exception.Create(''Attempt to access a released Pascal object.'');', 1);
  2745. Fps.WriteLn('Result:=pointer(ptruint(pasobj));');
  2746. Fps.DecI;
  2747. Fps.WriteLn('end;');
  2748. Fps.WriteLn;
  2749. Fps.WriteLn('function _GetClass(env: PJNIEnv; jobj: jobject; const ci: _TJavaClassInfo): TClass;');
  2750. Fps.WriteLn('var pasobj: jlong;');
  2751. Fps.WriteLn('begin');
  2752. Fps.IncI;
  2753. Fps.WriteLn('if jobj <> nil then');
  2754. Fps.WriteLn('pasobj:=env^^.GetLongField(env, jobj, ci.ObjFieldId)', 1);
  2755. Fps.WriteLn('else');
  2756. Fps.WriteLn('pasobj:=0;', 1);
  2757. Fps.WriteLn('if pasobj > 0 then');
  2758. Fps.WriteLn('Result:=TObject(ptruint(pasobj)).ClassType', 1);
  2759. Fps.WriteLn('else');
  2760. Fps.WriteLn('Result:=TClass(ptruint(-pasobj));', 1);
  2761. Fps.DecI;
  2762. Fps.WriteLn('end;');
  2763. Fps.WriteLn;
  2764. Fps.WriteLn('procedure _HandleJNIException(env: PJNIEnv);');
  2765. Fps.WriteLn('begin');
  2766. Fps.WriteLn('if env^^.ExceptionCheck(env) <> 0 then exit;', 1);
  2767. if p.OnExceptionProc <> nil then begin
  2768. Fps.WriteLn(Format('%s.%s;', [p.OnExceptionProc.Parent.Name, p.OnExceptionProc.Name]), 1);
  2769. p.OnExceptionProc.SetNotUsed;
  2770. end;
  2771. Fps.WriteLn('env^^.ThrowNew(env, env^^.FindClass(env, ''java/lang/Exception''), PAnsiChar(Utf8Encode(Exception(ExceptObject).Message)));', 1);
  2772. Fps.WriteLn('end;');
  2773. Fps.WriteLn;
  2774. Fps.WriteLn('procedure _HandleJavaException(env: PJNIEnv);');
  2775. Fps.WriteLn('begin');
  2776. Fps.WriteLn('if env^^.ExceptionCheck(env) <> 0 then raise Exception.Create(''Java exception.'');', 1);
  2777. Fps.WriteLn('end;');
  2778. Fps.WriteLn;
  2779. Fps.WriteLn('procedure _RaiseVarParamException(const VarName: string);');
  2780. Fps.WriteLn('begin');
  2781. Fps.WriteLn('raise Exception.CreateFmt(''An array with only single element must be passed as parameter "%s".'', [VarName]);', 1);
  2782. Fps.WriteLn('end;');
  2783. // Public support functions
  2784. Fps.WriteLn;
  2785. Fps.WriteLn('function _AllocMemory(env: PJNIEnv; jobj: jobject; size: jint): jlong;' + JniCaliing);
  2786. Fps.WriteLn('var p: pointer;');
  2787. Fps.WriteLn('begin');
  2788. Fps.WriteLn('GetMem(p, size);', 1);
  2789. Fps.WriteLn('FillChar(p^, size, 0);', 1);
  2790. Fps.WriteLn('Result:=ptruint(p);', 1);
  2791. Fps.WriteLn('end;');
  2792. Fps.WriteLn;
  2793. Fps.WriteLn('function _GetMemoryAsArray(env: PJNIEnv; jobj: jobject; SrcBuf: jlong; BufSize: jint): jarray;' + JniCaliing);
  2794. Fps.WriteLn('begin');
  2795. Fps.WriteLn('Result:=env^^.NewByteArray(env, BufSize);', 1);
  2796. Fps.WriteLn('env^^.SetByteArrayRegion(env, Result, 0, BufSize, pointer(ptruint(SrcBuf)));', 1);
  2797. Fps.WriteLn('end;');
  2798. Fps.WriteLn;
  2799. Fps.WriteLn('procedure _SetMemoryFromArray(env: PJNIEnv; jobj: jobject; DstBuf: jlong; SrcArray: jarray);' + JniCaliing);
  2800. Fps.WriteLn('begin');
  2801. Fps.WriteLn('env^^.GetByteArrayRegion(env, SrcArray, 0, env^^.GetArrayLength(env, SrcArray), pointer(ptruint(DstBuf)));', 1);
  2802. Fps.WriteLn('end;');
  2803. // Set support
  2804. Fps.WriteLn;
  2805. Fps.WriteLn('function _GetIntObjValue(env: PJNIEnv; jobj: jobject; const ci: _TJavaClassInfo): longint;');
  2806. Fps.WriteLn('begin');
  2807. Fps.IncI;
  2808. Fps.WriteLn('if jobj = nil then raise Exception.Create(''Attempt to access a NULL set.'');');
  2809. Fps.WriteLn('Result:=env^^.GetIntField(env, jobj, ci.ObjFieldId);');
  2810. Fps.DecI;
  2811. Fps.WriteLn('end;');
  2812. Fps.WriteLn;
  2813. Fps.WriteLn('function _CreateIntObj(env: PJNIEnv; Value: longint; const ci: _TJavaClassInfo): jobject;');
  2814. Fps.WriteLn('begin');
  2815. Fps.IncI;
  2816. Fps.WriteLn('Result:=nil;');
  2817. Fps.WriteLn('Result:=env^^.AllocObject(env, ci.ClassRef);');
  2818. Fps.WriteLn('if Result = nil then exit;');
  2819. Fps.WriteLn('env^^.SetIntField(env, Result, ci.ObjFieldId, Value);');
  2820. Fps.DecI;
  2821. Fps.WriteLn('end;');
  2822. // Preprocess units
  2823. for i:=0 to p.Units.Count - 1 do begin
  2824. if AnsiCompareText(p.Units[i].Name, 'system') <> 0 then
  2825. _ExcludeClasses(p.Units[i], nil);
  2826. end;
  2827. // Write units
  2828. for i:=0 to p.Units.Count - 1 do
  2829. with TUnitDef(p.Units[i]) do begin
  2830. WriteUnit(TUnitDef(p.Units[i]));
  2831. end;
  2832. WriteRecordSizes;
  2833. WriteClassTable;
  2834. WriteOnLoad;
  2835. Fps.WriteLn;
  2836. Fps.WriteLn('procedure ___doexit;');
  2837. Fps.WriteLn('begin');
  2838. Fps.WriteLn('_MethodPointersCS.Free;', 1);
  2839. Fps.WriteLn('end;');
  2840. Fps.WriteLn;
  2841. Fps.WriteLn('begin');
  2842. Fps.WriteLn('ExitProc:=@___doexit;', 1);
  2843. Fps.WriteLn('IsMultiThread:=True;', 1);
  2844. Fps.WriteLn('_MethodPointersCS:=TCriticalSection.Create;', 1);
  2845. Fps.WriteLn('end.');
  2846. finally
  2847. Fps.Free;
  2848. p.Free;
  2849. end;
  2850. end;
  2851. end.