writer.pas 85 KB

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