Recent

Author Topic: [SOLVED] LAMW: Add custom shared library to project  (Read 15939 times)

tk

  • Sr. Member
  • ****
  • Posts: 361
[SOLVED] LAMW: Add custom shared library to project
« on: November 11, 2016, 01:34:57 am »
I would like to test my shared library (cross compiled to Android/arm) in an Android app.

I managed to install LAMW and run a sample project.
However, I could not find an example how to load and manage custom shared libraries in a LAMW application.

So I just placed the library file libmylib.so to c:\lamw\projects\LamwGUIProject1\libs\armeabi-v7a\ where there already was libcontrols.so and wrote:

Code: Pascal  [Select][+][-]
  1. { TAndroidModule1 }
  2.  
  3. procedure TAndroidModule1.jButton2Click(Sender: TObject);
  4. var
  5.   LibName: string;
  6.   LibModule: HMODULE;
  7. begin
  8.   LibName := 'libmylib.so';
  9.   ShowMessage('Library: ' + LibName);
  10.   if FileExists(LibName) then
  11.     ShowMessage('Library file exists!')
  12.   else
  13.     ShowMessage('Library file does not exists!');
  14.   LibModule := LoadLibrary(FileName);
  15.   if LibModule <> 0 then
  16.   begin
  17.     ShowMessage('Library loaded!');
  18.   end else
  19.     ShowMessage('Library not loaded!');
  20. end;

After downloading to Android emulator and clicking the button it says: Library file does not exist.
When I rename the file LamwGUIProject1-debug.apk to a zip file and inspect its content the libmylib.so is there.
So what made I wrong? Is there some path info I must specify?
Thank you
« Last Edit: November 16, 2016, 12:44:16 pm by tk »

jmpessoa

  • Hero Member
  • *****
  • Posts: 2297
Re: LAMW: Add custom shared library to project
« Reply #1 on: November 11, 2016, 03:23:08 am »
Hi tk!

Quote
So I just placed the library file libmylib.so to c:\lamw\projects\LamwGUIProject1\libs\armeabi-v7a\ where there already was libcontrols.so 

Yes!


Now go to  folder ...\src\..... and edit  "Controls.java" like this:

Code: Java  [Select][+][-]
  1.  
  2.     try {  //your custom mylib ...
  3.         System.loadLibrary("mylib");
  4.     } catch (UnsatisfiedLinkError e) {
  5.          Log.e("JNI_Load_LibMylib", "exception", e);
  6.     }  
  7.  
  8.     try {     //default
  9.         System.loadLibrary("controls");
  10.     } catch (UnsatisfiedLinkError e) {
  11.          Log.e("JNI_Load_LibControls", "exception", e);
  12.     }  
  13.  
  14.  

And to prevent your modification from being lost,

go to menu:

 "Tools" -----> "[Lamw] Android Module Wizard" ---> "[Configure] CanUpdateJavaTemplates" 

and on dialog prompt choice "change to False".



« Last Edit: November 11, 2016, 03:24:56 am by jmpessoa »
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

tk

  • Sr. Member
  • ****
  • Posts: 361
Re: LAMW: Add custom shared library to project
« Reply #2 on: November 11, 2016, 11:10:41 am »
Hi jmpessoa,
now library loads fine, got Library loaded and even I could call a function from library!

But I still get Library file does not exist.

Everywhere else (Win, Linux, MAC) I first check with FileExists and then call LoadLibrary, with the same (full) library path.

Is there some difference between the parameter for LoadLibrary (works) and FileExists (doesn't work) on Android?

Thank you

jmpessoa

  • Hero Member
  • *****
  • Posts: 2297
Re: LAMW: Add custom shared library to project
« Reply #3 on: November 11, 2016, 05:46:12 pm »
Hi tk!

1. About "FileExists". The question is: "where android system save the library"? Android use a not trivial internal app file structure...

2. You really need to use "LoadLibrary"?

3. If possible send me a simple project with a custom minimalistic library. So
I will put it in "demos" project. If you have knowledge it would be interesting one compiled with Free Pascal and another with "C".

Thank you!
« Last Edit: November 11, 2016, 06:03:17 pm by jmpessoa »
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

tk

  • Sr. Member
  • ****
  • Posts: 361
Re: LAMW: Add custom shared library to project
« Reply #4 on: November 12, 2016, 10:44:56 am »
1. About "FileExists". The question is: "where android system save the library"? Android use a not trivial internal app file structure...

This I don't know! I only know the apk is saved under /data/app but where does the system extract it before run?
I only know that on Linux LoadLibrary does not search in current directory as on Windows.
You have to specify full path.
But Android is not Linux.


2. You really need to use "LoadLibrary"?

Yes absolutely. See this: http://forum.lazarus.freepascal.org/index.php/topic,34431.0.html.
Still I would prefer pascalish IDE even for the mobile dev. I'll play with LAMW a bit first to get the feeling.
For iOS it seems we have no other choice.

3. If possible send me a simple project with a custom minimalistic library. So
I will put it in "demos" project. If you have knowledge it would be interesting one compiled with Free Pascal and another with "C".

Yes I will. I'll put then other (more complex) LAMW demo with our real library to our commercial SW.

tk

  • Sr. Member
  • ****
  • Posts: 361
Re: LAMW: Add custom shared library to project
« Reply #5 on: November 12, 2016, 12:48:37 pm »
Further observations:
You can't add Forms unit to the library (mylib.so), the application crashes immediately.
Clearly because of the initialization code in the Forms unit.
So you can't access Application variable at all in the library.
I have LCL package in dependencies of the library project though, and customdrawn widgetset.

You can't add Forms unit even to the main app (libcontrols.so).

jmpessoa

  • Hero Member
  • *****
  • Posts: 2297
Re: LAMW: Add custom shared library to project
« Reply #6 on: November 12, 2016, 04:35:12 pm »
Quote
You can't add Forms unit to the library...

Yes, we can't have LCL dependency in LAMW project..

but, we can use many many FCL stuff. There are some graphics [fcl-image] e freetype examples.... see demos "AppTFPNoGUIGraphicsBridgeDemoXXX" and here
is an [old]  "readme.txt" for help with freetype and fcl-image on Android.

Quote
About "TFPNoGuiGraphicsBridge"

   ref. https://github.com/jmpessoa/tfpnoguigraphicsbridge

   "A wrapper over Free Pascal fcl-image ref. http://wiki.freepascal.org/fcl-image"

   "FPImage (fcl-image) draw images which won't be displayed in the screen [NoGUI !!!]. http://wiki.freepascal.org/Developing_with_Graphics


Hint: TFPNoGuiGraphicsBridge on Android [Lamw/Lazarus Android Module Wizard project!]

   --->>> Cross compile [Lamw/arm-android] project fail .... NO PANIC!

PANIC I: Compiling ... [please, read lazarus or/as laz4android and ...\fpc\2.7.1 or/as ...\fpc\3.1.1 etc..]

   "(FTFont.PPU and freetype.PPU) units NOT FOUND in "...\lazarus\fpc\2.7.1\units\arm-android\fcl-image" ???

   Solution:

   1. Goto "...\lazarus\fpc\2.7.1\source\packages\fcl-image\src" and copy

      ftfont.pp (if need change to .pas)
      freetype.pp (if need change to .pas)
      freetypeh.pp (if need change to .pas)

      to folder "...\tfpnoguigraphicsbridge" package folder and build AGAIN your project!

      Yes, now you got ftfont.ppu, ftfont.o, freetype.ppu etc... to "arm-android" !

   2. Copy THEM to folder  "...\lazarus\fpc\2.7.1\units\arm-android\fcl-image"
      So, others [future] projects will find its there!  [solved to "arm-android" !!!]

PANIC II: [building Lamw project cross-arm]::

   ".... : cannot find -lfreetype"

   Solution:

      Copy "libfreetype.so" to NDK location    "....\platforms\android-XX\arch-arm\usr\lib"
      where XX = 14 or 15 or 16... or 21 .. etc
      example: put "libfreetype.so" here: "..\ndkplatforms\android-15\arch-arm\usr\lib"

      For Lamw project you can look for "XX" value in menu:
      "Project" --->> "Project Options" ---> "Compile Options" -->> "Paths" --->> Libraries [-Fl]

PANIC III. Where I find a "libfreetype.so" for arm-android ?

   Go to demo "...\AppTFPNoGUIGraphicsBridgeDemo1\libs\armeabi" [Eclipse compatible Project]

   You will find an "all ready" there!

PANIC IV.  Where "libfreetype.so" will be load in java code?

   Go to "Controls.java" [\src\...\..] and uncomment this line:

      --->> System.loadLibrary("freetype");

   The code now will stay that way:

   //Load Pascal Library
   static {         
            System.loadLibrary("freetype");  // <<---uncommented here!
            System.loadLibrary("controls");          
   }

Other example:  we can play with FCL "fphttpclient", too: simply copy "fphttpclient.pp",  "httpprotocol.pp" and "httpprotocol.pp" to your project   "...\jni" folder  and "uses" ...

Thank you!


Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

tk

  • Sr. Member
  • ****
  • Posts: 361
Re: LAMW: Add custom shared library to project
« Reply #7 on: November 12, 2016, 09:50:54 pm »
Thank you, good to know.
My first feeling is LAMW is just a great tool, despite of the missing debugging and some other things!
Wish there was a LiMW tool as well (for iOS)!

Now I'll try to crosscompile our Linux UDP driver, which is based on Synapse.
If it is not running then I'll have to write a new one for Android using udpsocket.
This will be another library loaded by the library I spoke off above.

So I'll make regular dll hell under Android. Great isn't it? :D

jmpessoa

  • Hero Member
  • *****
  • Posts: 2297
Re: LAMW: Add custom shared library to project
« Reply #8 on: November 13, 2016, 04:48:03 am »
Ok. I was able to generate the customs android-arm ".so" from codes in "Pascal"  and "C". And everything worked fine!

Here  are my findings:

(1)
Prepare to Linker:
Copy "libmylib.so" to NDK location    "....\platforms\android-XX\arch-arm\usr\lib"
      where XX = 14 or 15 or 16... or 21 .. etc
      example: put "libmylib.so" here: "..\ndkplatforms\android-15\arch-arm\usr\lib"

      For Lamw project you can look for "XX" value in menu:
      "Project" --->> "Project Options" ---> "Compile Options" -->> "Paths" --->> Libraries [-Fl]

(2)
Put "libmylib.so" in folder "...\libs\armeabi"  where there already was "libcontrols.so"

(3)
Edit "Controls.java" to load "mylib", too ["...\src\...\..."]:

Code: Java  [Select][+][-]
  1.     try {
  2.         System.loadLibrary("mylib");
  3.     } catch (UnsatisfiedLinkError e) {
  4.          Log.e("JNI_Load_LibMyLib", "exception", e);
  5.     }
  6.  

(4)
Copy  "mylib.pas" interface unit  to "....\jni" folder

"mylib.pas" code example:
Code: Pascal  [Select][+][-]
  1. unit mylib;
  2.  
  3. interface
  4.  
  5.    function addp(a: longint;  b: longint):longint; cdecl; external 'libmylib.so' name 'addp';
  6.  
  7. implementation
  8.  
  9. end.
  10.  

5. Add "mylib.pas" interface unit  to  "unit1.pas"  [uses]

6. Try call the function "addp"
Code: Pascal  [Select][+][-]
  1. procedure TAndroidModule1.jButton1Click(Sender: TObject);
  2. var
  3.   sumPascal: longint;
  4. begin
  5.   sumPascal:= addp(13, 15);
  6.   ShowMessage(IntToStr(sumPascal));
  7. end;
  8.  

7. Success!

NOTE:  I did not need to use pascal code like "LibModule := LoadLibrary('libmylib.so');" This was handled by java [step "3"]
« Last Edit: November 13, 2016, 04:59:25 am by jmpessoa »
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

tk

  • Sr. Member
  • ****
  • Posts: 361
Re: LAMW: Add custom shared library to project
« Reply #9 on: November 13, 2016, 10:34:34 am »
Hi jmpessoa thank you much for further help.

I have to use LoadLibrary because I need the library to be loaded dynamically.
I generate the interfaces for the library with my tool (PWIG, is already part of my KControls in the bitbucket repo) and they are the same for Win, Linux, MAC, Android....

I think currently it works fine (on my Android 4 device, not on the emulator but who cares, I can try putting it to the usr/lib folder according to your point 1 so maybe it helps even for the emulator)

Actually I thought about some automation of the library management in LAMW/Controls.java.

I mean not having to disable the "[Configure] CanUpdateJavaTemplates" because it is needed when I add some new UI to the module.
I think I might be able to do this myself in LAMW, could you point me in correct direction?

EDIT:
I thought about adding a new page to Android Project Options named External Libraries, there a simple list and then generate the code to Controls.java.
But maybe you'll be quicker than me, as with the demo libs written in Pascal and C :) I am still playing with my real project and want to test as much as possible first.
Later I will send you a simple demo for a dynamically loaded library as promised :), where the interfaces for the caller (libcontrols.so) and callee (libmylib.so) were generated by PWIG. Here you can use classes from the library transparently as if they were declared in the main app.

EDIT2:
Now I'll try to crosscompile our Linux UDP driver, which is based on Synapse.
If it is not running then I'll have to write a new one for Android using udpsocket.

As I suspected Synapse does not work under Android. Question is now how to use jUDPSocket in my custom library where I don't have (and already can't have) the jApp reference.  :-\
« Last Edit: November 13, 2016, 03:59:22 pm by tk »

jmpessoa

  • Hero Member
  • *****
  • Posts: 2297
Re: LAMW: Add custom shared library to project
« Reply #10 on: November 13, 2016, 05:11:11 pm »
Quote
I mean not having to disable the "[Configure] CanUpdateJavaTemplates" because it is needed when I add some new UI to the module....

No, You can continue adding new UI to the module.... no problem!
[In fact update only synchronizes the project templates com the framework templates..]


Quote
I thought about adding a new page to Android Project Options named External Libraries, there a simple list and then generate the code to Controls.java.

Great idea! I will see what I can do...

Quote
As I suspected Synapse does not work under Android. Question is now how to use jUDPSocket in my custom library where I don't have (and already can't have) the jApp reference. 

I will think about...But we should continue to seek a pure pascal solution. In a similar case [http] I was able to use FCL stuff.   

Is there  a FCL UDP implementation?

Maybe someone here in the forum could point us to a [simple] pascal UDP implementation...

« Last Edit: November 13, 2016, 05:14:49 pm by jmpessoa »
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

tk

  • Sr. Member
  • ****
  • Posts: 361
Re: LAMW: Add custom shared library to project
« Reply #11 on: November 13, 2016, 06:46:24 pm »
No, You can continue adding new UI to the module.... no problem!
[In fact update only synchronizes the project templates com the framework templates..]

Did not work for me. When I tried to add jTimer for example I had to turn it on and then again off, to get jTimer.java and some jTimer stuff to Controls.java. Then I had to include the library loads again to Controls.java.
So did I make sth. wrong?

Great idea! I will see what I can do...

Ok. You are the master here :)

Is there  a FCL UDP implementation?

I tried SynCrtSock from MORMOT but that did not compile, then I tried to activate linux (kylix) port for Synapse and took an extraction of LibC for that (so that the linker did not complain about missing libs), but app crashed immediately.

So now I'll try to use the socket API first. There is libc.so in the ndk so the socket api should be basically supported.

And actually I can't use the jUDPsocket at all because the driver library has to be completely standalone, would not work without the java counterpart.

jmpessoa

  • Hero Member
  • *****
  • Posts: 2297
Re: LAMW: Add custom shared library to project
« Reply #12 on: November 13, 2016, 07:38:55 pm »

There is some FPC UDP stuff here:

Quote
C:\lazarus\fpc\3.1.1\source\packages\libenet


Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

tk

  • Sr. Member
  • ****
  • Posts: 361
Re: LAMW: Add custom shared library to project
« Reply #13 on: November 13, 2016, 08:19:30 pm »

C:\lazarus\fpc\3.1.1\source\packages\libenet

Voila, this connects to ENET (http://enet.bespin.org/) which in turn connects directly to BSD sockets.
This might work.
Finally I gave up to get Synapse running on Android. Too complex code and I can't debug.
Hopefully the ENET lib helps me, will report then, thank you!

jmpessoa

  • Hero Member
  • *****
  • Posts: 2297
Re: LAMW: Add custom shared library to project
« Reply #14 on: November 13, 2016, 08:48:38 pm »
Quote
Quote
No, You can continue adding new UI to the module.... no problem!
[In fact update only synchronizes the project templates com the framework templates..]
Did not work for me. When I tried to add jTimer for example I had to turn it on and then again off, to get jTimer.java and some jTimer stuff to Controls.java. Then I had to include the library loads again to Controls.java.
So did I make sth. wrong?

I did some test here... works as expected ...The jTime [and others] stuff was include and my "loadlibrary" was preserved in "Controls.java"... try "save all"  or/and  "run-->>build" before "look for" change in your code base...
« Last Edit: November 13, 2016, 09:15:37 pm by jmpessoa »
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

 

TinyPortal © 2005-2018