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);
返回值:完全限定的類名(即包名,由“/”分隔,後跟類名).
歡迎各位交流指正!