Jni學習1--靜態註冊和動態註冊
阿新 • • 發佈:2019-01-30
1.jni 靜態註冊
第一步:新建java類:
System.loadLibrary後面會講到
第二步:通過javah 命令生成.h檔案 (固定命令) (包名)
C:\MyNDKTest\mylibrary\build\intermediates\classes\release>javah -jni ndk.example.com.mylibrary.JniTest
注意:找到class檔案的包名的上一級目錄,否則無法生成.h檔案
第三步:將生成的h檔案拷貝到jni目錄,然後新建一個cpp或者c檔案,內容如下:
在jni生成的getMax函式:Java_ndk_example_com_mylibrary_JniTest_getMax
jni函式命名規則: 1 .包名+類名+函式名
2.java包名的“.”改成“_”
3.如果java函式名簽名裡面多了“_”則在前面加1
比如:java包名com.test 類名Class_getmin
那麼生成com_test_Class_1getmin()函式
#include <jni.h> /* Header for class ndk_example_com_mylibrary_JniTest */ #ifndef _Included_ndk_example_com_mylibrary_JniTest #define _Included_ndk_example_com_mylibrary_JniTest #ifdef __cplusplus extern "C" { #endif /* * Class: ndk_example_com_mylibrary_JniTest * Method: getMax * Signature: (II)I*/ JNIEXPORT jint JNICALL Java_ndk_example_com_mylibrary_JniTest_getMax (JNIEnv *evn, jobject, jint num1, jint num2){
if(num1>num2) return num1 else return num2; } #ifdef __cplusplus } #endif #endif
第四部:生成jar和so
使用命令gradlew makeJar命令生成jar 和so,參考 https://mp.csdn.net/postedit/79502214
1.jni 動態註冊
第一步:定義方法名: JNIEXPORT jint JNICALL getMax(JNIEnv *evn, jobject jobject1, jint num1, jint num2){ LOGD("-------------------------getMax----------------------"); return (num1>num2)?num1:num2; } JNIEXPORT void JNICALL test(JNIEnv *evn, jobject jobject1){ LOGD("-------------------------test----------------------"); } 第二步:定義 JNINativeMethod陣列 JNINativeMethod method_table[] = { {"getMax", "(II)I", (int*) getMax}, {"test", "()V", (void*) test} }; 第三步:重寫JNI_OnLoad JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){ jclass myClass; JNIEnv* env = NULL; //註冊時在JNIEnv中實現的,所以必須首先獲取它 jint result = -1; if((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) //從JavaVM獲取JNIEnv,一般使用1.4的版本 return -1; myClass = (*env)->FindClass(env, className); if(myClass == NULL) { return -1; } int size=sizeof(method_table)/sizeof(method_table[0]); if((*env)->RegisterNatives(env,myClass,method_table,size)<0) { return -1; } return JNI_VERSION_1_4; //這裡很重要,必須返回版本,否則載入會失敗。 }
完整的C程式碼如下:
#include <jni.h> #include "stddef.h" #include <android/log.h> static const char *TAG = "Test"; #define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args) #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args) #define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args) #ifndef _Included_ndk_example_com_mylibrary_JniTest #define _Included_ndk_example_com_mylibrary_JniTest #ifdef __cplusplus extern "C" { #endif JNIEXPORT jint JNICALL getMax(JNIEnv *evn, jobject jobject1, jint num1, jint num2){ LOGD("-------------------------getMax----------------------"); return (num1>num2)?num1:num2; } JNIEXPORT void JNICALL test(JNIEnv *evn, jobject jobject1){ LOGD("-------------------------test----------------------"); } //方法陣列,JNINativeMethod的第一個引數是Java中的方法名,第二個引數是函式簽名,第三個引數是對應的方法指標。 //Java方法的簽名一定要與對應的C++方法引數型別一致,否則註冊方法可能失敗。 JNINativeMethod method_table[] = { {"getMax", "(II)I", (int*) getMax}, {"test", "()V", (void*) test} }; static const char* const className="ndk/example/com/mylibrary/JniTest"; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){ jclass myClass; JNIEnv* env = NULL; //註冊時在JNIEnv中實現的,所以必須首先獲取它 jint result = -1; if((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) //從JavaVM獲取JNIEnv,一般使用1.4的版本 return -1; myClass = (*env)->FindClass(env, className); if(myClass == NULL) { return -1; } int size=sizeof(method_table)/sizeof(method_table[0]); if((*env)->RegisterNatives(env,myClass,method_table,size)<0) { return -1; } return JNI_VERSION_1_4; //這裡很重要,必須返回版本,否則載入會失敗。 } #ifdef __cplusplus } #endif #endif