从相应的java类外部调用jni函数

时间:2017-01-08 14:57:37

标签: android function java-native-interface naming

已知jni函数通常命名如下(来自Oracle docs):

  

动态链接器根据名称解析条目。本机方法名称由以下组件连接:

     
      
  • 前缀Java_
  •   
  • 错误的完全合格的班级名称
  •   
  • 下划线(“_”)分隔符
  •   
  • 错误的方法名称
  •   

因此,方法的名称始终应包含相应的Java类名,并且不能从该类外部调用。如果您从其他类Android Studio检查器调用此方法,则会发出如下警告:

  

在Java中报告本机方法声明,其中在项目中找不到相应的JNI函数。

如果你运行,你会收到 java.lang.UnsatisfiedLinkError:找不到本机方法例外。

因此我的问题是:如何使用本机函数创建共享库,可以从任何 Java类调用?

更具体。我有Java类MyActivity。我需要从这个类中调用一些jni函数。据我所知,根据Oracle doc,该函数应该像Java_xxx_yyy_zz_MyActivity_func1一样命名为smth。然后想象一下,我也想从另一个Android应用程序调用此函数。我将我的lib * .so复制到libs文件夹,但我将无法调用我的func1,找不到coz本机函数。为了在新应用程序中使用该功能的可能性,我需要在那里创建相同的文件夹层次结构xxx / yyy / zzz和类MyActivity,之后我将能够调用func1但仅从该MyActivity类调用。但是,如果我想把它叫到另一个班级,我该怎么办?

1 个答案:

答案 0 :(得分:1)

- 新答案,给出问题编辑 -

感谢您的澄清。 AFAIK,没有自动方法将相同的本机方法与多个Java方法相关联。但是,您可能会发现一些有用的解决方法:

(1)调用共享的外观。假设您不需要将Java实例对象传递给该方法,首先在我的原始答案中声明一个外观类,并在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);

然后从你想要的任何其他类中调用它:

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

(2)使用RegisterNatives调用将一个C方法与多个java方法相关联,如here所述。但是,我怀疑你会发现这很方便,因为必须从“C”完成注册,所以你还需要一些首先调用的启动方法。

---旧答案 -

我不确定你到底是怎么回事。如果您的问题是您不想创建包含这些方法的对象,只需将它们声明为static:

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

javah然后生成此本机方法签名:

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

您的其他Java代码可以免费致电:

JniStuff.method1("something", 123);

不实例化JniStuff类型的对象