writer.pas 102 KB

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