前幾天分享了一篇關於TS流解析的文章,有朋友在問,你怎麼不使用動態註冊呀,什麼是JN動態註冊呢?今天給你們介紹使用一下。java
jni native註冊主要有2種,靜態註冊和動態註冊,其中靜態註冊是咱們經常使用的,由於部分項目用到jni的接口不多,經過靜態註冊就能很方便快速的實現,不過當接口多起來時就會略顯麻煩,而且靜態註冊的包名關聯,很容易致使錯誤,排版也很差看,而動態註冊就很好的解決了這一問題。android
特色:實現快速,可是函數名也很是長,不適合管理數組
它的編譯形式是根據函數名來遍歷查找java和jni函數之間的關聯,而後靜態調用app
extern "C" JNIEXPORT jstring JNICALL Java_com_blur_blurbyjnidemo_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */) { std::string hello = "Hello from C++"; return env->NewStringUTF(hello.c_str()); }
特色:每一個方法一一映射,簡單明瞭,不容易出錯,便於管理jvm
它經過在jvm中註冊jni函數映射表,再根據函數映射表去調用對應名稱和參數的函數,ide
/* * used in RegisterNatives to describe native method name, signature, * and function pointer.from jni.h */ typedef struct { const char* name;//java方法名稱 const char* signature;//jni對應的函數參數和返回值的描述值,具體參考第三節 void* fnPtr;//fnPtr是函數指針,指向C函數 } JNINativeMethod;
動態註冊的幾個步驟:函數
native-lib.cpp:測試
#include <jni.h> #include "mDebug.h" #include <string> #ifndef NELEM #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) #endif //c測試方法 static jstring j_hello(JNIEnv* env, jobject thiz ) { const char* hello = "Hello from C++"; return env->NewStringUTF(hello); } static jstring j_hello2(JNIEnv* env, jobject thiz ) { const char* hello = "test-----------------------------2"; return env->NewStringUTF(hello); } /** * 1. 綁定對應的方法映射表 */ static const JNINativeMethod jniMethods[] = { {"stringFromJNI", "()Ljava/lang/String;", (void*)j_hello}, {"stringFromJNI2", "()Ljava/lang/String;", (void*)j_hello2}, }; /**註冊方法*/ static int registerMethods(JNIEnv * env, const char* className ,const 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 registerAllMethods(JNIEnv* env) { const char* kClassName = "com/blur/blurbyjnidemo/NativeLib";//指定要註冊的類 return registerMethods(env, kClassName,jniMethods, NELEM(jniMethods)); } /*** * 2. jni_onload加載時註冊映射表中的方法 */ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; if (vm->GetEnv( (void**) &env, JNI_VERSION_1_4) != JNI_OK) { return -1; } mInfo("JNI_OnLoad"); if (!registerAllMethods(env)) {//註冊全部方法 return -1; } return JNI_VERSION_1_4; }
mDebug.h:this
#ifndef __MDEBUG_H__ #define __MDEBUG_H__ #include <jni.h> #include <android/log.h> #ifndef BASETYPES #define BASETYPES //typedef _Null_terminated_ char *PSZ; #endif /* !BASETYPES */ #ifndef CAMERA_LOG_TAG #define CAMERA_LOG_TAG "debug" #define mDebug(format, ...) __android_log_print(ANDROID_LOG_ERROR,CAMERA_LOG_TAG, format" [File:%s, Line:%d, Function:%s]",##__VA_ARGS__, __FILE__, __LINE__ , __FUNCTION__) #define mInfo(format, ...) __android_log_print(ANDROID_LOG_INFO,CAMERA_LOG_TAG, format" [File:%s, Line:%d, Function:%s]",##__VA_ARGS__, __FILE__, __LINE__ , __FUNCTION__) #define mMsg(...) __android_log_print(ANDROID_LOG_INFO,CAMERA_LOG_TAG, __VA_ARGS__) #endif #endif
NativeLib.java:spa
package com.blur.blurbyjnidemo; public class NativeLib { // Used to load the 'native-lib' library on application startup. static { System.loadLibrary("native-lib"); } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native String stringFromJNI(); public static native String stringFromJNI2(); }
上面動態註冊結構第二項參數,須要填入參數和方法返回的映射值:
這個字符串的結構是一個括號後面再接字符串:
1. "()"中的描述的是函數的傳入參數描述
2. 括號後面接的是返回值描述
好比:"()V":表示 void function(); (JF)Z":表示 boolean function(long l,float f);等
基本類型類型對照表
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[]
非基本類型,好比class類型的,以"L"開頭,經過"/"隔開包名與類名,以";"結尾,好比:
Ljava/lang/String; String jstring