1. 程式人生 > >JNI介面自己命名與註冊

JNI介面自己命名與註冊

2.熟悉了JNI的使用,我們肯定有點不爽的是:

  •     javah 自動生成檔名是又臭又醜;
  •     而且在實際專案中,總不能新增一個函式,就去重新生成一把,我們最喜歡的是改動最小使用最方便。

3.現在我們就來11解決

    要使用我們自己命名的.C/.CPP文件,當然就是要實現它的實現過程:

    jint JNI_OnLoad(JavaVM *vm, void *reserved); //vm: a pointer to the current VM structure. reserved:unused pointer.

        Optional function defined by dynamically linked libraries.
        The VM calls JNI_OnLoad when the native library is loaded (for example, through System.loadLibrary

).

      return: Return the required JNI_VERSION constant.Such as: JNI_VERSION_1_4 or JNI_VERSION_1_1

      當我們在JAVA專案中載入庫時,首先呼叫OnLoad函式,因此我們首相實現自己的OnLoad函式:

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
	JNIEnv* env = NULL;
	jint result = -1;
	if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
		return -1;
	}

    if (!registerNativeMethods(env, JNIREG_CLASS, gMethods, sizeof(gMethods) / sizeof(gMethods[0]))) {//註冊方法
		return -1;
	}
	//成功
	return (result = JNI_VERSION_1_4);
}

//實現註冊:

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;
}

整體流程就是這樣。

    其中具體的細節,我們來看看:

        ①GetEnv 的使用:

         GetEnv 在C++使用:         jint GetEnv(void **penv, jint version);
         GetEnv 在C使用:           jint GetEnv(JavaVM *vm, void **env, jint version);
        ②#define JNIREG_CLASS     "javaTestJNI/myJavaTestJni"      //指定要註冊的JAVA類(包/類)

        ③實現我們要註冊的函式方法陣列:

         static JNINativeMethod  gMethods[] = {     //任意新增我們自己的方法
             { "sum", "(II)I", (void*)sum },
          };

            其中:JNINativeMethod型別定義可在jni.h檢視,

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

              同時需要學習的是:引數的signature的官方定義:

   

            eg: 本例中:int sum(int , int)  --> (II)I 

       ④jclass FindClass(JNIEnv *env, const char *name);

        返回值:完全限定的類名(即包名,由“/”分隔,後跟類名).

歡迎各位交流指正!