Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2014-08

Exporting functions in an Android library

3 messages · 2 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Sergio Flores

Hi again!
This mail is the continuation of the Androids threads problem. As you guys said, the threads problem seems to be caused by using a old version of the compiler, so I went and compiled fpc from trunk, for Android target.
Then I tried compiling my game using the cross compiler I just built.

I had to make some changes to the compilation options: Replaced -Tlinux with -Tandroid
Replaced -CfVFPV2 with -CfVFPV3
Removed -mfloat-abi=hard
Added new unit path (units\rtl-objpas, seems it was necessary for dateutils now)

And then it compiled fine, generated a .so, like before. All seems ok, so I compile my java code, and make an apk. When I try running the game now it /dalvikvm( 5667): Trying to load lib
/data/data/com.terra.minimon3d/lib/libterraARMV7.so 0x424967b8 E/AndroidRuntime( 5667): java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1307]: 111 cannot locate 'PASCALMAIN'...

Strange... So I run nm on the .so file to check exported symbols. D:\code\minimonhd\trunk\Android\libs\armeabi-v7a>nm -g libterraARMV7.so U FPC_THREADVARTABLES
U INITFINAL
U PASCALMAIN
(and others, calloc, malloc, FPC_RESOURCESTRINGTABLES, etc)

Where are my own exported JNI functions, they are gone? I had like 30 of them, that were correctly exported with an older FPC.

Confused by this, I compile the game again, but this time with the older FPC version.
I then run nm on the .so and the functions are all there... 0005aa08 T JNI_OnLoad
0005aa34 T JNI_OnUnload
00059b30 T Java_com_pascal_terra_TERRALibrary_ApplicationContextLost 00059b2c T Java_com_pascal_terra_TERRALibrary_ApplicationGetOrientation Etc...
Something curious, PASCALMAIN is not anywhere in the export symbols now. And I don't even understand why this is being called when I load the library in the Java side?

My own exported functions are all declared in the main file. They are defined like this:

Procedure Java_com_pascal_terra_TERRALibrary_ApplicationShutdown(env,
obj:Pointer);  stdcall; export; [public];
Begin
...
End;

Note that even in the old compiler, if the functions are defined outside the main file they were not exported, compiler bug or some kind of limitation?
Also the part "export; [public];" seems necessary in Android, otherwise they were also not exported correctly. I don't really understand what [public] means, and sadly could not find documentation about it. Finally, in the end of the main file I have an exports section, listing all functions I want to export, all worked before so what changed that causes the symbols to not be exported in the .so?

And why is this PASCALMAIN being exported, since I'm compiling a library not a program?

Here's the complete compilation options I'm using, just in case I'm missing something
-TAndroid -a -Parm -CpARMV7 -CfVFPV3 -gl -vewnhi -Xd -Sg -O- -XParm-linux-androideabi- -FUbuild -FEandroid\libs\%TARGET_OUTPUT%\ -olibterra%TARGET%.so
(plus fpc\units\rtl, rtl-objpas and 10 other paths belonging to my own units)

Regards,
Sérgio

Reply by email

Sven Barth
to Sergio Flores
Sergio Flores wrote 6 lines
I had to make some changes to the compilation options: Replaced -Tlinux with -Tandroid Replaced -CfVFPV2 with -CfVFPV3 Removed -mfloat-abi=hard Added new unit path (units\rtl-objpas, seems it was necessary for dateutils now)

Yes, the change to -Tandroid and the inclusion of rtl-objpas is expected. Afterall Android is now a fully supported target and the latter was because we've split up the RTL a bit.

Show quoted text 8 lines
My own exported functions are all declared in the main file. They are defined like this: Procedure Java_com_pascal_terra_TERRALibrary_ApplicationShutdown(env, obj:Pointer); stdcall; export; [public]; Begin ... End;

Better try to use an "exports" section in the mainfile instead of "export; [public];". See here (even related to Java) http://wiki.freepascal.org/Using_Pascal_Libraries_with_Java and here http://www.freepascal.org/docs-html/ref/refse100.html

Sidenote: the standard calling convention for Java is AFAIK "cdecl". It does not matter on ARM as there is all calling conventions are the same anyway, but on android-x86 that will matter...

Also the part "export; [public];" seems necessary in Android, otherwise they were also not exported correctly. I don't really understand what [public] means, and sadly could not find documentation about it.

Then you didn't look good enough ;)
http://www.freepascal.org/docs-html/ref/refsu77.html#x185-19500014.9.12

Finally, in the end of the main file I have an exports section, listing all functions I want to export, all worked before so what changed that causes the symbols to not be exported in the .so?

Exporting functions without an "exports"-clause is a bit fragile. Could be that a bug was fixed or a bug was introduced. I don't know currently...

And why is this PASCALMAIN being exported, since I'm compiling a library not a program?

Even libraries have a main entrypoint. It's the "begin ... end." inside the library file and this one is also responsible for initializing all used units.

Regards,
Sven

Reply by email

Sergio Flores

Hi Sven, thanks for the fast answer.
I did not found that about [public] because I thought it was just an option of "export", and so always search for export documentation.

And I did have an exports function in main file, I told about it in my previous mail, that was not the problem.

I checked better the compilation output, and I found out why there is a problem.
There are too many assembler errors in all of my files!

build\TERRA_Localization.s:3184: Error: only lo regs allowed with immediate -- `mov r8,#0'
build\TERRA_Localization.s:3212: Error: Thumb does not support conditional execution
build\TERRA_Localization.s:3214: Error: unshifted register required -- `mvn r3,#-2147483648'

Thus the object files are not generated correctly, they were probably empty or something?
So I went and rebuilt FPC, to make sure it was only ok, and then I saw it, those assembler errors also appeared during FPC compilation...

I tried many combinations of switches and finally found the culprit, it was -CpARMV7
I changed it to -CpARMV5 and changed from -CfVFPV3 to -CfVFPV2. Now FPC builds without assembly errors and my game too, and the export symbols are there.
The game runs without crashing, and even threads work now, so good, I'm making progress!

However...
As far I know armv5 has inferior performance, eg: does not support hard floating point?
I really needed armv7 to work, so I investigated a bit more. It seems that trunk fpc supports lots of armv7 variations, and the proper one seems to be armv7a.
I compiled again FPC and my game with this instruction set, and it runs great!

So the problem was just that, I dont know why the previous FPC version worked fine with that instruction set thought, maybe armv7 defaulted to armv7a or something?

Again, thanks again to everyone that made FPC a reality, you guys are great!

Reply by email