在實際應用中,除了在JNI層對部分功能進行C++的實現,同時還會有在JNI中對Java函數的調用以實現某種邏輯的聯通。
在JNI中回調Java函數,其實是經過反射機制來實現的,經過反射機制取得目標函數所在的類,以及其名稱,經過NDK提供的接口在JNI層進行調用。java
package com.test.jni; public class TestFunction { public static void testFunc(){ Log.d("tag from Java", "worked!"); } }
const char[] method_class_from_java = "com/teest/jni/TestFunction"; const char[] method_name_from_java = "testFunc"; jclass cls_str_id = jenv->FindClass(method_from_java); jmethodID m_Java_TestFunc = jenv->GetStaticMethodID(cls_str_id, method_name_from_java, "()V"); jenv->CallStaticObjectMethod(cls_str_id, m_Java_TestFunc);
經過如上方式就能夠實如今JNI中調用Java中函數,具體解釋以下:android
其中jenv爲JNI函數的環境參數,注意在反射獲取java函數時其參數及返回值數據類型的簽名。web
關於NDK中的簽名規則以下:api
字符簽名 | jni中類型 | java中類型 |
---|---|---|
V | void | void |
Z | jboolean | boolean |
I | jint | int |
J | jlong | long |
D | jdouble | double |
F | jfloat | float |
B | jbyte | byte |
C | jchar | char |
S | jshort | short |
而對於數組而言,須要以"["開始,組合以上規則便可,具體對應關係表以下:數組
字符簽名 | jni中類型 | java中類型 |
---|---|---|
[Z | jbooleanArray | boolean[] |
[I | jintArray | int[] |
[J | jlongArray | long[] |
[D | jdoubleArray | double[] |
[F | jfloatArray | float[] |
[B | jbyteArray | byte[] |
[C | jcharArray | char[] |
[S | jshortArray | short[] |
以上均爲基本數據類型的簽名,對於另外兩種狀況:svg
"Landroid/os/FileUtils;"
"Landroid/os/FileUtils$FileStatus;"
講到這裏,基本上十分清楚了,可是有一個特殊狀況,細心的同窗應該能夠發現,以上列表中咱們並無標記String類型。那是由於確實存在一個例外狀況必定要小心,那就是String類。在使用其簽名時,要使用:函數
"Ljava/lang/String;"
若是直接使用jstring,那就會找不到。這個例外狀況必定要小心。線程
當Java期待JNI中返回值爲String[]時,好比:指針
//java native API public native String[] getValues(); //JNI native code JNIEXPORT jobjectArray JNICALL getValues(JNIEnv *jenv, jobject obj){ jclass stringClass = jenv->FindClass("java/lang/String"); char** user_ids = calling-other-apis //.... jobjectArray pidsArray = jenv->NewObjectArray((jsize) 10, stringClass, nullptr); for (int i = 0; i < 10; i++) { jstring userId = jenv->NewStringUTF(user_ids[i]); jenv->SetObjectArrayElement(pidsArray, i, userId); jenv->DeleteLocalRef(userId); } return pidsArray; }
從以上的實例中看出,JNI中並無’jstringArray’的類型與String[]匹配,能夠替代使用的則是jobjectArray.code
其中最值得關注的是如下兩點:
1. 針對String的FindClass,其供反射的關鍵詞爲'java/lang/String' (注意String的簽名是'Ljava/lang/String;') 2. 該函數在JNI中註冊時簽名能夠寫爲: '()[Ljava/lang/String;'
在每一個JNI對Java層開發的native函數中,第一第二個參數均是以下形式:
static void JNICALL test (JNIEnv *jenv, jobject obj)