Unit initialization lazarus / 43-Android ---------------------------------------------------------------------- Daniello · 2012-06-25 23:41 I'm trying to compile my game engine code to Android. My units initialization code does not seem to be called, other than that, everything compiles file. What may cause this? ---------------------------------------------------------------------- felipemdc · 2012-06-26 20:25 I am pretty sure that unit initialization works, or else neither the LCL nor the example project would work. It might be something else that is going wrong. Is you initialization calling LCL routines? It shouldn't. ---------------------------------------------------------------------- Daniello · 2012-06-26 20:28 Oh, I'm not using Lazarus nor LCL, I'm compiling it from the command line (might be the reason why the initialization is not being called correctly). I'm using the following arguments (fpc I'm using is the precompiled Windows binary): -Tlinux -Parm -CpARMV6 -vewnhi -Xd -O- -XP -dANDROID -olibmain.so -Cccdecl -a ---------------------------------------------------------------------- jmpessoa · 2013-07-07 16:34 I'm having problems in same context .... even a simple Unit like: Code: [Select]unit Unit2; {$mode delphi} interface uses   Classes, SysUtils; var   FStrDummy: string;   FIntDummy: integer; implementation initialization     FStrDummy:='Dummy unit2 Message ...';     FIntDummy:= 1234; end. does not work ...    Can anyone give a hint? Thanks! ---------------------------------------------------------------------- Blaazen · 2013-07-07 17:47 How do you know that it does not work? (I mean: What do you expect it should do? ) I use initialization and it always worked as expected. ---------------------------------------------------------------------- jmpessoa · 2013-07-07 17:51 Well, when I try to "print "  FStrDummy variable is "empty"... Thank you! ---------------------------------------------------------------------- Blaazen · 2013-07-07 18:04 I assume you use Unit2 from Unit1 (it is in uses). I just tested, variable is initialized even if I try it from initialization of the first unit (i.e. initialization of Unit2 is done before initialization of Unit1). You should give here a full demo. IMO the problem is elsewhere in your project. ---------------------------------------------------------------------- jmpessoa · 2013-07-07 18:25 Ok,  follow my project: Code: [Select]library pascaljni1; {$mode delphi} uses   SysUtils,  jni,  Unit2; const   curClass:JClass=nil;   nativeCodeLoaded:JfieldID=nil; function getString(PEnv: PJNIEnv; this: JObject): JString; cdecl; var   str: string; begin   str:= FStrDummy; // <<---------- "empty" here...   Result:= (PEnv^).NewStringUTF(PEnv,PChar(str)); end; function getInt(PEnv: PJNIEnv; this: JObject): JInt; cdecl; begin   Result:= JInt(FIntDummy); //  <<---------- "zero" here.... end; const NativeMethods:array[0..1] of JNINativeMethod = (    (name:'getString';     signature:'()Ljava/lang/String;';     fnPtr:@getString;),    (name:'getInt';     signature:'()I';     fnPtr:@getInt;)); function JNI_OnLoad(vm: PJavaVM; reserved: pointer): JInt; cdecl; begin  {just curiosity: initialization here is ok!} // <<-----------    result:= JNI_VERSION_1_6; end; procedure JNI_OnUnload(vm: PJavaVM; reserved: pointer); cdecl; begin end; exports   JNI_OnLoad name 'JNI_OnLoad',   JNI_OnUnload name 'JNI_OnUnload',   getString name 'Java_org_jmpessoa_app1_PascalJNI1_getString',   getInt name 'Java_org_jmpessoa_app1_PascalJNI1_getInt'; begin   {curiosity: variables initializarion here too does not work!}//<<------- end. Thank you again! ---------------------------------------------------------------------- Daniello · 2013-07-07 18:54 Olá amigo, vou-te dar a minha solução (Im gonna give you my solution). Declare this somewhere: procedure internal_initializeunits; external name 'FPC_INITIALIZEUNITS'; Then on the jniload function call internal_initializeunits(), this should fix your problem ---------------------------------------------------------------------- jmpessoa · 2013-07-07 19:03 Muito Obrigado Amigo! (Thank you my friend!) Vou tentar isso! (I'll try it!) Abraços. ---------------------------------------------------------------------- jmpessoa · 2013-07-07 19:18 Hi Daniello...  the emulator stay in loop! ---------------------------------------------------------------------- Daniello · 2013-07-07 19:22 Quote from: jmpessoa on July 07, 2013, 09:18:37 pmHi Daniello...  the emulator stay in loop!  Hmm, that is strange. I never used the emulator though  Do you call the initialization where, in jni_load? Try moving it to another place. In my case I have a function called ApplicationInit that calls the fpc unit initialization. This ApplicationInit function is called from Java, when the app is ready to work ---------------------------------------------------------------------- jmpessoa · 2013-07-07 19:29 Yes, please, see here: Code: [Select]library pascaljni1; {$mode delphi} uses   SysUtils, jni, Unit2; const   curClass:JClass=nil;   nativeCodeLoaded:JfieldID=nil; procedure internal_initializeunits; external name 'FPC_INITIALIZEUNITS'; //<< ----- here! function getString(PEnv: PJNIEnv; this: JObject): JString; cdecl; var   str: string; begin   str:= FStrDummy; // <<---------- "empty" here...   Result:= (PEnv^).NewStringUTF(PEnv,PChar(str)); end; function getInt(PEnv: PJNIEnv; this: JObject): JInt; cdecl; begin   Result:= JInt(FIntDummy); //  <<---------- "zero" here.... end; const NativeMethods:array[0..1] of JNINativeMethod = (    (name:'getString';     signature:'()Ljava/lang/String;';     fnPtr:@getString;),    (name:'getInt';     signature:'()I';     fnPtr:@getInt;)); function JNI_OnLoad(vm: PJavaVM; reserved: pointer): JInt; cdecl; begin    internal_initializeunits();//<< ----- here!   result:= JNI_VERSION_1_6; end; procedure JNI_OnUnload(vm: PJavaVM; reserved: pointer); cdecl; begin end; exports   JNI_OnLoad name 'JNI_OnLoad',   JNI_OnUnload name 'JNI_OnUnload',   getString name 'Java_org_jmpessoa_app1_PascalJNI1_getString',   getInt name 'Java_org_jmpessoa_app1_PascalJNI1_getInt'; begin    {just curiosity: variables initializarion here too does not work!} end. Thank you! ---------------------------------------------------------------------- Daniello · 2013-07-07 19:36 Yeah, remove it from the jni_load and make a separate function  that you can call from Java. Also you should save the VM pointer on jni_load, to use later whenever you need to call Java stuff. And make sure that the jni_load is being called, write to the log there (and watch with adb -logcat). I had lots of problems with jni_load not being called at startup ---------------------------------------------------------------------- jmpessoa · 2013-07-07 19:43 Ok. Just a Question about: " This ApplicationInit function is called from Java, when the app is ready to work....". I think this is in MainActivity "onCreate",  this is correct? Thank you! ---------------------------------------------------------------------- Daniello · 2013-07-07 20:01 Yes, on the oncreate is a good place to do that ---------------------------------------------------------------------- jmpessoa · 2013-07-07 22:13 I tried but did not work! and also tried something like: Code: [Select]library pascaljni1; {$mode delphi} uses   SysUtils, jni, Unit2; procedure internal_initializeunits; external name 'FPC_INITIALIZEUNITS'; //<< --- here! function getString(PEnv: PJNIEnv; this: JObject): JString; cdecl; begin end; function getInt(PEnv: PJNIEnv; this: JObject): JInt; cdecl; begin end; function JNI_OnLoad(vm: PJavaVM; reserved: pointer): JInt; cdecl; begin   result:= JNI_VERSION_1_6; end; procedure JNI_OnUnload(vm: PJavaVM; reserved: pointer); cdecl; begin end; exports   JNI_OnLoad name 'JNI_OnLoad',   JNI_OnUnload name 'JNI_OnUnload',   getString name 'Java_org_jmpessoa_app1_PascalJNI1_getString',   getInt name 'Java_org_jmpessoa_app1_PascalJNI1_getInt'; begin    internal_initializeunits(); //<< ----- here!     {curiosity:  here too does not was called!} end. and it did not work too! ---------------------------------------------------------------------- Daniello · 2013-07-07 22:27 Well, in the initialization unit does not work, since the initialization of units is never called (that is the problem you are trying to solve). Have you tried writing a procedure that calls the unit-initialization, and then call that procedure from Java, using JNI? If you dont know how to do this I can teach you tomorrow. Another option would be trying a different build of the compiler. Pascal Android developement it is still very unstable, sadly. My current setup has 2 different builds, one for arm7, other for arm5. Not using the right compiler build causes strange bugs, crashes and other problems  Search for ZenGL, a pascal 2d game engine, they have a build that works, I'm using that now ---------------------------------------------------------------------- jmpessoa · 2013-07-07 23:31 Yes,  I write  "a procedure that calls the unit-initialization, and then call that procedure from Java, using JNI"... Ok. I will try another compiler and too on a real device! Many Thanks to you my friend!