欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C语言JNI的动态注册详解

程序员文章站 2022-06-15 12:48:26
目录jni的静态注册就是javah生成头文件,本章第一篇已经讲过,现在我们来讲讲第二种方式,jni动态注册。首先是module的build.gradle:android { compilesdk...

jni的静态注册就是javah生成头文件,本章第一篇已经讲过,现在我们来讲讲第二种方式,jni动态注册。首先是module的build.gradle:

android {
    compilesdkversion 30
    buildtoolsversion "30.0.3"

    defaultconfig {
        applicationid "com.jhzl.a7_jni_2way"
        minsdkversion 21
        targetsdkversion 30
        versioncode 1
        versionname "1.0"

        testinstrumentationrunner "androidx.test.runner.androidjunitrunner"

        externalnativebuild {
            cmake {
                cppflags ""
            }
        }
    }
    buildtypes {
        release {
            minifyenabled false
            proguardfiles getdefaultproguardfile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    externalnativebuild {
        cmake {
            path "cmakelists.txt"
        }
    }
}

那我们的activity的本地方法贴出来把:

public class mainactivity extends appcompatactivity {

    @override
    protected void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        setcontentview(r.layout.activity_main);
        textview addtv = findviewbyid(r.id.add_tv);
        textview subtv = findviewbyid(r.id.sub_tv);
        addtv.settext("加法计算:"+add(10,20));
        subtv.settext("减法计算:"+sub(10,20));
    }
    static {
        //加载静态库
        system.loadlibrary("native-lib");
    }

    public native int add(int a,int b);
    public native  int sub(int a,int b);

}

接着就是cmakelists.txt

# 指定cmke版本
cmake_minimum_required(version 3.4.1)
add_library(native-lib
        shared
        src/main/cpp/hello.cpp) #添加.c源文件
include_directories(src/main/cpp/include) #添加头文件的位置
target_link_libraries(native-lib
        log) #选择要使用的库

最后,我们贴出今天的重头戏hello.h:

#ifndef practicle_hello_h
#define practicle_hello_h
extern "c"
#endif //practicle_hello_h

hello.cpp:

#include <jni.h>
#include "hello.h"
#include<android/log.h>
#define tag "helloworld-jni" // 这个是自定义的log的标识
#define logd(...) __android_log_print(android_log_debug,tag ,__va_args__) // 定义logd类型
#define logi(...) __android_log_print(android_log_info,tag ,__va_args__) // 定义logi类型
#define logw(...) __android_log_print(android_log_warn,tag ,__va_args__) // 定义logw类型
#define loge(...) __android_log_print(android_log_error,tag ,__va_args__) // 定义loge类型
#define logf(...) __android_log_print(android_log_fatal,tag ,__va_args__) // 定义logf类型
#ifdef __cplusplus
extern "c" {
#endif

//对应mainactivity的add
jint add(jnienv *env, jobject clazz, jint a, jint b) {
    return a + b;
}

//对应mainactivity的sub
jint sub(jnienv *env, jobject clazz, jint a, jint b) {
    return a - b;
}

//回调函数 在这里面注册函数
jint  jni_onload(javavm* vm, void* reserved){
    jnienv* env = null;
    //env赋值
    logd("getenv");
    //获取jnienv
    if(vm->getenv((void**)&env,jni_version_1_6)!= jni_ok){
        logd("getenv failed");
        return -1;
    }
    //获取一个class对象,对应java类mainactivity
    jclass  mainactivity = env->findclass("com/jhzl/a7_jni_2way/mainactivity");

    /**
     * add : java方法名
     * (ii)i 里面是两个jint,返回jnit
     * add,c函数指针,传递的参数应该是env,jobject,包括签名的(ii)两个jint,一个jnit返回值
     *
     */
    jninativemethod methods_mainactivity[] = {
            {"add", "(ii)i", (jint *) add},
            {"sub", "(ii)i", (jint *) sub}

    };
    env->registernatives(mainactivity,methods_mainactivity,sizeof(methods_mainactivity)/ sizeof(methods_mainactivity[0]));
    env->registernatives(mainactivity,methods_mainactivity,sizeof(methods_mainactivity)/ sizeof(methods_mainactivity[1]));
    //返回jni 的版本
    return jni_version_1_6;
}


#ifdef __cplusplus
}
#endif

最后运行的效果是:

C语言JNI的动态注册详解

jni参数对照表:

C语言JNI的动态注册详解

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注的更多内容!

相关标签: C语言 JNI