writer.pas 97 KB

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