calling jni method from other jni library - android

Is it possible to call jni method of 1 library from another method of different jni library ?
for eg: I have 2 libraries lib_1.so and lib_2.so.
I want to call a method get_interface() of lib_1.so from lib_2.so.
Is this possible?
If yes, please share the example of how this can be done.

When calling from one shared library to another, its really no longer jni, its just native code(c->c or c++ -> c++). Include the .h and invoke the function as you would normally, passing whatever parameters the function requires.

I think you can do dlopen("lib2.so") from lib1.so so you have a handle to your lib2.so library and then using that handle you can call the methods.

Related

Finding function pointer if the Java_... naming is not used

I'm debugging an android application and am confusing about one android shared library and here i wanna explain the problem.
There is a native function defined in java code (java side) like this:
public static native void nativeInitialize();
Package:
package com.example.ExClass;
I loaded the shared library in IDA Pro.
I thought that i can find that function in exported functions and it should be something like this Java_com_example_ExClass_nativeInitialize
But the function is not in export list and as i debugged the java side codes, i know the function is calling from java but i don't know how it is working ?!
If the name-mangling scheme (Java_...) is not used, then it is possible the library uses the RegisterNatives approach to associate method names with function pointers. Try searching for structs that embed the string "nativeInitialize", they should be the methods argument to RegisterNatives. Look through the JNI_OnLoad function for the call site.
On Aarch64 assembly it should look like:
ldr x4, [x8,#1720] # RegisterNatives is the 215th member, times 8 bytes per pointer
bl x4 # Could also be a br if this was the last call of the function

Android, import external library to NDK

i am making an Android Shapefile reader app on Android with the use of NDK. I want to use C++ to parse shape files. I found library "Shapefile C Library". Github: https://github.com/sw897/shapelib.
I am using Android studio and have no idea how to import it to my Android project so i could use functions described in: http://shapelib.maptools.org/shp_api.html
Any tips?
First, start hacking away at the Hello-JNI example from Google:
https://github.com/googlesamples/android-ndk/tree/master/hello-jni
Use that as a test bed.
Then, create a Java Class with public native methods that let you interact with your library. Something of a high level API, probably to pass a file name or buffer to SHPOpenLL and return a pointer to the ShapeFile context (ShapeHandle). Looks like your library is written in C, so you should be able to write a similar interface to query the shapefile passing a (jint) c-style cast of your ShapeHandle pointer.
Next, you need to play around with javah to generate the header for your shapefile interface. Once the header is generated, you can use it to implement your interface in a .cc file. From there you will basically make Java calls to your C interface and it will return jobjects. (jint, jbool, jstring, etc...)
I'm looking at the ShapeLib that you want to use and while it's easy enough, there will be some gotchas.
You will need to implement SAHooks for file I/O. I suggest looking at NVFile for an example how to access APK files (or downloaded files). You will need to init it using activity.context.assetmanager. Then use nv_file to wrap FRead/FSeek/etc...
Passing info back to java is going to be tough. Personally, I would build a Java class to hold the shape information and fill it out on the C side. However, you might be tempted to query these parameters from the SHPObject one at a time. Will be slow, but less error prone.
E.g.
// Java
MyJavaShapeObject obj = new MyJavaShapeObject();
_c_retrieveShapeObj((jint)pShapeFile, obj);
// C
java_blah_blah_c_retrieveShapeObj(JNIEnv* env, jclass activity, jint theShapeFile, jobject theObj){
ShapeHandle pShapeFileHandle = (ShapeHandle)theShapeFile; // c style conversion
// http://stackoverflow.com/questions/11647646/how-to-use-the-jni-to-change-the-fields-of-a-java-class
// http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp16613
// http://stackoverflow.com/a/36759159/7949696
}

Making sense of symbol table entry (when header function is not present)

I have a JNI function in a C++ library.
When I create the library using cmake (but forget to put function declaration) in the header file, the library is created successfully.
When I look for function name in library symbol table I get following output
nm libuserlibrary.so | grep printxx
00506e60 T _Z60Java_com_example_user_myapplication_userlibrary_printxxP7JNIEnv_P8_jobject
But when I give function declaration in the header file, I get following output
nm libuserlibrary.so | grep printxx
00506e50 T Java_com_example_user_myapplication_userlibrary_printxx
Why is there this difference between these two symbol table entries? What is the purpose of _Z60 and P7JNIEnv_P8_jobject around the function name?
I also noticed that in the first case, I cannot call the JNI funciton from Android java code (it says unsatisfied-linker-error, implementation not found).
C++ allows function overloads and namespaces like Java does. So, it annotated the function name with parameter information so the linker can bind to the correct overload.
JNI was designed for C which does not allow function overloads or namespaces. So it invented it's own annotation system and provides the javah tool to help you use it. The header can be used in C++ too. C++ was designed to allow some functions to be called as if they written in C. The header has code that indicates that to the compiler. So, put it all together and you can write Java-callable functions in C++.

Android NDK overriding methods

I have 2 NDK libraries (.so files ) in my android project and there is a method in the first library that is also called (used) in the first library and I want the second library to override the called (used) method found in the first library. Is it possible to just have the same name and parameters and load the second library after the first like
System.load(first);
System.load(second);
Will this override the first method or do I have to do something else? If so, please specify.
Thanks in advance for your time.
Once a symbol has been resolved (by System.load) it will not be changed. The definition loaded from first will be used.

dlopen on Android ndk

I made a c++ main aplication that loads a so library also made by me.
Both sources shares a common header (TestFlags.h).
Inside TestFlags.h I have an class and a pointer declaration of it which is intended to be global to the whole application, that is define a instance in the main app and use it inside a library function.
class TestFlags {
public:
TestFlags() : behaviour(1)
{}
int behaviour;
};
extern __attribute__ ((visibility("default"))) TestFlags * gpTestFlags;
then a sequence of execution steps followed to reach the named goal are:
main application creates a new instance of TestFlags ---> gpTestFlags = new TestFlags();
main application load the library ---> dlopen(library.so, RTLD_LAZY|RTLD_GLOBAL)
invoke a function that resides inside the library which uses previous instance declared ---> gpTestFlags->behaviour = 2;
Received a SIGSEGV: Segmentation fault because gpTestFlags is NULL
It seems that inside the library gpTestFlags instance is not seen for some reason.
Same thing also happens with other static class I have, values which are configured on the main application not seen inside the library.
As far I can research it seems that the library manages a totally different memory space for those declarations like if it was duplicated.
This is the expected way dlopen() would work.
The two modules have independent global symbols called gpTestFlags. If you try to link them together, the linker would scream about duplicates.
You can declare the pointer in library as weak, or you can use dlsym() to resolve the linkage programmatically.

Categories

Resources