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
最后运行的效果是:
jni参数对照表:
总结
本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注的更多内容!
下一篇: mmdetection梳理