靜態(tài)注冊
靜態(tài)注冊
native
方法的過程逮刨,就是 Java 層聲明的native
方法和 JNI 函數(shù)是一一對應(yīng)的
public class HelloJNI {
static{
System.loadLibrary("main");
}
public native void dynamicLog();
public native void staticLog();
}
#include <jni.h>
#define LOG_TAG "main.cpp"
#include "mylog.h"
JNIEXPORT void JNICALL Java_com_wwe_HelloJNI_staticLog (JNIEnv *env, jobject obj)
{
LOGE("static register log ");
}
那么有沒有方法讓 Java 層的 native 方法和任意的 JNI 函數(shù)鏈接起來呕缭,當(dāng)然是可以的,這就得使用動態(tài)注冊的方法修己。接下來就看看如何實(shí)現(xiàn)動態(tài)注冊的恢总。
動態(tài)注冊
因?yàn)?Java 層和 C/C++ 的數(shù)據(jù)類型或者對象不能直接相互的引用或者使用,JNI 層定義了自己的數(shù)據(jù)類型睬愤,用于銜接 Java 層和 JNI 層片仿。了解一下
JNI_OnLoad函數(shù)
#include <jni.h>
#define LOG_TAG "main.cpp"
#include "mylog.h"
static void nativeDynamicLog(JNIEnv *evn, jobject obj){
LOGE("hell main");
}
// 一般會動態(tài)注冊多個 native 方法
JNINativeMethod nativeMethod[] = {{"dynamicLog", "()V", (void*)nativeDynamicLog},};
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
JNIEnv *env;
if (jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return -1;
}
LOGE("JNI_OnLoad comming");
jclass clz = env->FindClass("com/wwe/HelloJNI");
// 第三個參數(shù)為注冊 native 方法的數(shù)量
env->RegisterNatives(clz, nativeMethod, sizeof(nativeMethod)/sizeof(nativeMethod[0]));
return JNI_VERSION_1_4;
}
JavaVM
結(jié)構(gòu)體定義了以下函數(shù):
DestroyJavaVM
AttachCurrentThread
DetachCurrentThread
GetEnv
獲取Java對象,完成動態(tài)注冊
jint RegisterNatives(jclass clazz, const JNINativeMethod* methods, jint nMethods)
JNINativeMethod
結(jié)構(gòu)體是描述 Java 層 native 方法的戴涝,它的定義如下:
typedef struct {
const char* name; // Java 層 native 方法的名字
const char* signature; // Java 層 native 方法的描述符
void* fnPtr; // 對應(yīng)JNI 函數(shù)的指針
} JNINativeMethod;
JNIEnv 結(jié)構(gòu)體
它指向一個函數(shù)表滋戳,該函數(shù)表指向一系列的 JNI 函數(shù)钻蔑,我們通過調(diào)用這些 JNI 函數(shù)可以實(shí)現(xiàn)與 Java 層的交互啥刻,這里簡單的看看幾個定義的函數(shù):
// CallVoidMethod() 根據(jù) methodID 調(diào)用對應(yīng)對象中的方法,并且該方法的返回值為 Void 類型咪笑。
..........
jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
jboolean GetBooleanField(jobject obj, jfieldID fieldID)
jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)
CallVoidMethod(jobject obj, jmethodID methodID, ...)
CallBooleanMethod(jobject obj, jmethodID methodID, ...)
..........