已知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类调用。但是,如果我想把它叫到另一个班级,我该怎么办?
答案 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类型的对象