我想首先说请不要让我使用javah工具,我写这些jni函数原型比使该工具正常工作更幸运。
我知道我正在正确加载我的jni库,因为它们在我离开类结构时工作。
我有一些包名: 包com.bb.me;
public class test {
test2 iTest = null;
public parent test()
{
iTest = new test();
return iTest;
}
//putting my native methods here work just fine
//public native void init();
//etc
}
上述函数的c jni函数原型如下所示:
JNIEXPORT void JNICALL Java_com_bb_me_test_init(JNIEnv* e, jobject i) {}
如果我通过重命名它inita
来破坏上面的函数签名并调用该函数我得到如下错误:
找不到原生Lcom / bb / me / test的实现; .init :()V
另一方面,如果我将本机函数移动到内部类,如下所示:
class test2 extends parent {
//public native void init();
}
然后尝试调用相同的函数,jni会以不同的方式向我抱怨未实现的函数,但这次它看起来像这样:
找不到原生Lcom / bb / me / test $ test2; .init :()V
的实现我原本以为如果我将jni函数签名编辑成这样的东西:
JNIEXPORT void JNICALL Java_com_bb_me_test_test2_init(JNIEnv* e, jobject i) {}
该功能可以正常工作,但似乎并非如此。
这个jni函数签名中“ $ ”美元符号的含义是什么?
找不到原生Lcom / bb / me / test $ test2; .init :()V
的实现如何在不使用javah工具的情况下移动此本机函数的位置并更新jni函数签名?
答案 0 :(得分:3)
我想首先说请不要让我使用javah工具,我写这些jni函数原型比使该工具正常工作更幸运。< / p>
我不会要求你使用javah
- 虽然很难不这样做 - 但我必须至少说我觉得这句话令人惊讶。我发现javah
非常容易使用。如果它不能正常工作&#34;正确&#34;对你来说,我倾向于怀疑你有错误的期望。
&#34; $&#34;这个jni函数签名中的美元符号是什么意思?
$
从嵌套类的类名称中划分嵌套类的简单名称。这是JVM内部名称表示的一个方面,这是JNI的工作原理。
如何在不使用javah工具的情况下移动此本机函数的位置并更新jni函数签名?
您可以参考Oracle's documentation for mapping Java native method names to C function names。期望的本机函数名称基于本机方法类的完全限定JVM名称,基于本机方法的非限定名称,如果它已超载,则基于其签名。如果将本机方法移动到另一个类,则需要更改函数名称以反映新位置,如果尚未完成,则还可能需要将函数签名编码为名称。
内部类的JVM名称为com/bb/me/test$test2
。假设该方法没有重载,那么与该类中驻留的本机方法相对应的C函数名称将为Java_com_bb_me_test_00024test2_init()
。参数是一个不同的故事 - 它们依赖于Java端方法的参数以及本机方法是否是静态的。我不在这里解决它们。