JNI动态注册

概述

jni简单的说就是java调用c,注册c的方法有两种,一种是静态注册,一种是动态注册。静态注册就是通过javah生成.h文件来实现,不是本文重点。动态注册通过JNI_OnLoad来注册native方法,下面直接上代码。

java层

public class FileUtils {
    static {
        System.loadLibrary("native-lib");
    }
    public static native void diff(String path, String pattern_Path, int file_num);
}

直接新建一个类来管理native方法,其他activity的代码就不贴了,直接调用即可。

native层

调用System.loadLibrary(“native-lib”);会进入JNI_OnLoad,通过这个方法来注册。


jint JNI_OnLoad(JavaVM *vm, void *reserved) {


    JNIEnv *env = NULL;
    jint result = -1;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4)) {

        return -1;
    }

    assert(env != NULL);

    registerNatives(env);

    return JNI_VERSION_1_4;

}

这个方法主要是通过JavaVM 去获取JNIEnv ,有了这个指针就可以注册native方法了,在看registerNatives方法之前需要做一些准备工作。

JNIEXPORT void JNICALL native_diff
        (JNIEnv *, jclass, jstring, jstring, jint) {
    LOGI("%s\n", "注册成功");
}

static const JNINativeMethod gMethods[] = {
        {
                "diff", "(Ljava/lang/String;Ljava/lang/String;I)V", (void *) native_diff
        }
};

首先声明一个方法,这个方法的名字可以任意指定,这个就是native注册的方法,接着声明一个结构体数组
gMethods[],里头包含了注册的对应关系。JNINativeMethod 的声明

typedef struct {
    const char* name;
    const char* signature;
    void*       fnPtr;
} JNINativeMethod;

name是java层的方法名,signature是对应的方法指针,fnPtr是c层的函数指针,做一一对应关系。
最后看看registerNatives方法。

int registerMainNative(JNIEnv *env) {
    LOGI("register main start");

    jclass clz = env->FindClass("com/example/ty/sourceproject/MainActivity");
    if (NULL == clz) {
        LOGI("mainclass is null");
        return JNI_FALSE;
    }

    if (env->RegisterNatives(clz, mainMethod, NELEM(mainMethod)) < 0) {
        LOGI("registernatives error");
        return JNI_FALSE;
    }
    return JNI_TRUE;

}

方法很简单就是通过env来注册多个方法,NELME和LOGI的宏定义是这样的

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))

工作作完,剩下的直接调用逻辑即可。

总结

动态注册主要就是3步:
1.通过JNI_OnLoad获取env指针。
2.编写native方法以及对应的结构体数组
3.注册方法

关于动态注册和静态注册的优缺点:

静态注册:
优点:每个class都需要使用javah生成一个头文件,并且生成的名字很长书写不便;初次调用时需要依据名字搜索对应的JNI层函数来建立关联关系,会影响运行效率
缺点:用javah 生成头文件方便简单

动态注册:
优点:使用一种数据结构JNINativeMethod来记录java native函数和JNI函数的对应关系
移植方便(一个java文件中有多个native方法,java文件的包名更换后)
缺点:使用麻烦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值