RegisterNatives的使用方法
在Android中通過jni調(diào)用本地方法(c/c++)去枷,通常使用javah生成規(guī)范的頭文件,定義一個(gè)函數(shù)實(shí)現(xiàn)本地方法堵泽,函數(shù)名必須使用本地方法的全類名的規(guī)范來寫井誉。
Java_ + 包名 + 類名+ 接口名
注意名字之間用下劃線抡句,下面是示例:
JNIEXPORT jstring Java_com_example_test_MainActivity_helloworld(JNIEnv *, jclass );
有沒有覺得這種寫法太反人類了,其實(shí)jni還提供了RegisterNative函數(shù)手動(dòng)的注冊native方法赋秀,該方法可以自由命名函數(shù)利朵,不必像上述方法那樣拘泥特定煩雜的命名方式。
RegisterNatives
使用示例:
static int registerNativeMethods(JNIEnv* env)
{
jclass clazz;
clazz = env->FindClass("com/example/test/MainActivity");
if (clazz == NULL) {
return JNI_FALSE;
}
if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) < 0) {
return JNI_FALSE;
}
return JNI_TRUE;
}
RegisterNatives
中第二個(gè)參數(shù)gMethods
是一個(gè)二維數(shù)組猎莲,代表著這個(gè)class里的每一個(gè)native方法所對應(yīng)的實(shí)現(xiàn)的方法绍弟。寫法如下示例:
static JNINativeMethod gMethods[] = {
{"helloworld", "()Ljava/lang/String;", (void*)Jni_helloworld}};
第三個(gè)參數(shù)代表要指定的native的數(shù)量。
這時(shí)將前面在jni中聲明的
jstring JNIEXPORT jstring Java_com_example_test_MainActivity_helloworld(JNIEnv *, jclass );
改為
jstring helloworld(JNIEnv *, jclass);
是不是清爽了很多著洼!
JNI字段描述符
在使用RegisterNatives
注冊本地方法中比較容易出錯(cuò)的地方就是JNINativeMethod gMethods[]
其中的()Ljava/lang/String;
樟遣。
先解釋下()Ljava/lang/String;
的含義,它是一種對函數(shù)返回值和參數(shù)的編碼身笤,這種編碼叫做JNI字段描述符(JavaNative Interface FieldDescriptors)年碘。
JNI字段描述符的規(guī)則是在括號(hào)里放置參數(shù),在括號(hào)后面放置返回類型:
(參數(shù)描述符)返回類型
例如()Ljava/lang/String;
表示對應(yīng)的java中的helloworld方法無傳入?yún)?shù)展鸡,返回類型為String屿衅,即String helloworld();
這個(gè)示例可能過于簡單,下面再舉幾個(gè)例子:
(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
表示String f(String a,Object b);
([B)Ljava/lang/String;
表示String f(byte [] bytes);
這里B
表示java中的byte
類型莹弊,[
表示數(shù)組涤久,[B
表示byte []
。
以此類推忍弛,
[Ljava/lang/String;
表示String []
[Ljava/lang/Object;
表示Object[]
如果是二維數(shù)組int[][]
,用[[I
表示响迂。
另外要注意的是,引用類型(除基本類型的數(shù)組外)通常以"L"開頭细疚,以";"結(jié)尾蔗彤,中間是用"/" 隔開的包及類名。所以";"分號(hào)是屬于引用類型的一部分,因此參數(shù)中如果有多個(gè)參數(shù)的話是不用;
間隔的然遏。如:
(BI)V
表示void f(byte b, int i);
(ILjava/lang/String;)V
表示void f(int i,String s);
最后附上java類型與jni中字符對應(yīng)的關(guān)系表:
Java 類型 | 符號(hào) |
---|---|
Boolean | Z |
Byte | B |
Char | C |
Short | S |
Int | I |
Long | J |
Float | F |
Double | D |
Void | V |
objects對象 | 以L 開頭贫途,以; 結(jié)尾,中間是用/ 隔開的包及類名待侵。比如:Ljava/lang/String; 如果是嵌套類丢早,則用$ 來表示嵌套。例如 (Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z
|