NDK動態註冊

博客導航

c/c++和java交互,需要找到雙方各自對應的函數或方法來調用。這種產生聯繫的方式有兩種方式,一個是靜態註冊,另一種事動態註冊。動態註冊是比靜態註冊的好處是不需要JNI那一套很長的命名。

其他的規則和靜態註冊無異,只是註冊的地方不同而已。

下面是動態註冊的方式。

/**
 * 動態註冊
 */
extern "C" {

jstring stringFromJNI2(JNIEnv *env, jobject instance) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

jint add(JNIEnv *env, jclass clazz, jint a, jint b) {
    LOGE("ADD!!");
    return a + b;

}

#define JNIREG_CLASS "com/slzr/ndk/NDKManager"//指定要註冊的類
/**
* 方法對應表
*/
static JNINativeMethod gMethods[] = {
//        {"stringFromJNI2", "()Ljava/lang/String;", (void *) stringFromJNI2},
        {"add",            "(II)I",                (void *) add}
};

/*
* 爲某一個類註冊本地方法
*/
static int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *gMethods,
                                 int numMethods) {
    jclass clazz;
    clazz = env->FindClass(className);
    if (clazz == NULL) {
        return JNI_FALSE;
    }
    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
        return JNI_FALSE;
    }

    return JNI_TRUE;
}


/*
* 爲所有類註冊本地方法
*/
static int registerNatives(JNIEnv *env) {
    return registerNativeMethods(env, JNIREG_CLASS, gMethods,
                                 sizeof(gMethods) / sizeof(gMethods[0]));
}

/*
* System.loadLibrary("lib")時調用
* 如果成功返回JNI版本, 失敗返回-1
*/
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    jint result = -1;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    assert(env != NULL);
    if (!registerNatives(env)) {//註冊
        return -1;
    }
    //成功
    result = JNI_VERSION_1_6;
    return result;
}
}

這裏說明一下,JNI_OnLoadSystem.loadLibrary加載完動態庫執行的函數,寫在jni.h裏面。
registerNatives寫本地的方法。gMethods寫方法列表,第一參數是java裏面的方法名稱,第二參數是方法輸入參數,第三個參數是c/c++裏面對應的函數。它的結構類型如下:

typedef struct {
    const char* name;
    const char* signature;
    void*       fnPtr;
} JNINativeMethod;

第二個參數可以參照java的反射。

字符 Java類型 C類型
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

數組則以"["開始,用兩個字符表示。
[I       jintArray      int[]
[F     jfloatArray    float[]
[B     jbyteArray    byte[]
[C    jcharArray    char[]
[S    jshortArray   short[]
[D    jdoubleArray double[]
[J     jlongArray     long[]
[Z    jbooleanArray boolean[]

gMethods裏面的第二參數()表示輸入參數,有多少就寫多少進去。比如說兩個int參數,就寫(II)。括號後面跟着的是返回值V表示沒有返回值void。Ljava/lang/String;對應是String類型。Ljava/lang/Object;對應是Object類型。

在java層面仍然需要native 編寫。

    public native int add(int a, int b);

附件:
demo源碼地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章