1. 程式人生 > >Jni學習1--靜態註冊和動態註冊

Jni學習1--靜態註冊和動態註冊

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