calling jni function from outside of corresponding java class

1.9k Views Asked by At

it's known that jni function usually named as follows (from Oracle docs):

Dynamic linkers resolve entries based on their names. A native method name is concatenated from the following components:

  • the prefix Java_
  • a mangled fully-qualified class name
  • an underscore (“_”) separator
  • a mangled method name

So method's name always should contain corresponding Java class name and cannot be called from outside of this class. In case u're call this method from other class Android studio inspector gives the warning like this:

Reports native method declarations in Java where no corresponding JNI function is found in the project.

And if u run that u will receive java.lang.UnsatisfiedLinkError: Native method not found exception.

And thus my question is: how to create shared library with native functions, which could be called from any Java class?

To be more concrete. I have Java class MyActivity. And i need to call some jni function from this class. As i understand according Oracle doc that function should be named smth like Java_xxx_yyy_zz_MyActivity_func1. Then imagine, that i also want to call this function from another android app. I copy my lib*.so to libs folder but i will not be able to call my func1, coz native function will not be found. For possibility of using that function in new app i need to create the same folders hierarchy that is xxx/yyy/zzz and class MyActivity there and after that i will be able to call func1 but only from that MyActivity class. But what should i do if i want to call that fron another class?

1

There are 1 best solutions below

0
On

-- new answer, given question edits --

Thanks for the clarification. AFAIK, there is no automatic way to associate the same native method with multiple Java methods. However, there are a couple workarounds that you might find useful:

(1) Call a shared facade. Assuming you don't need to pass the Java instance object to the method, first declare a facade class as in my original answer, and implement it in C:

public class JniStuff {
    public static native void method1(String s, int i);
}

JNIEXPORT void JNICALL Java_net_redpoint_scratch_JniStuff_method1
      (JNIEnv *, jclass, jstring, jint);

then call it from any other class you want:

public class MyClass {
   public static void method1(String s, int i) {
      JniStuff.method1(s, i);
   } 
}

(2) Use the RegisterNatives call to associate the one C method with multiple java methods, as explained here. However, I doubt that you will find this to be convenient as the registration must be done from "C", so you would also need some startup method that is called first to do that.

--- old answer --

I'm not sure what you are after, exactly. If your problem is that you don't want to create an object containing the methods, just declare them static:

package net.redpoint.scratch;
public class JniStuff {
    public static native void method1(String s, int i);
}

javah then generates this native method signature:

JNIEXPORT void JNICALL Java_net_redpoint_scratch_JniStuff_method1
      (JNIEnv *, jclass, jstring, jint);

Your other Java code is free to call:

JniStuff.method1("something", 123);

without instantiating an object of type JniStuff