jni原理和实现

一、jni原理

主要就是通过数据类型签名和反射来实现java与c/c++方法进行交互的

数据类型签名对应表

javac/c++
booleanZ
byteB
charC
shortS
intI
longL
floatF
doubleD
voidV
objectL开头,然后以/分割包的完整类型,后面再加; 比如String的签名就是Ljava/long/String
Array以[开头,在加上数组元素类型的签名, 比如int[],签名是[I,int[][]的签名是[[I, object[]的签名是[Ljava/lang/Object

数据类型对应表

javac/c++
booleanjboolean
bytejbyte
charjchar
shortjshort
intjint
longjlong
floatjfloat
doublejdouble
voidvoid

引用类型对应表

javac/c++
stringjstring
objectjobject
classjclass
byte[]jbyteArray

二、实现jni

增加这三处

在这里插入图片描述

		ndk{// 设置支持的架构abiFilters 'armeabi-v7a', 'arm64-v8a'}externalNativeBuild {cmake {path file('src/main/cpp/CMakeLists.txt')version '3.18.1'}}

CMakLists.txt

# 声明并命名项目。
cmake_minimum_required(VERSION 3.18.1)# 声明并命名项目。
project("myc")# 创建并命名一个库,设置其类型为静态或共享,并提供其源代码的相对路径。
# 您可以定义多个库,CMake会为您构建它们。
# Gradle会自动将共享库与您的APK一起打包。
add_library( # 设置库的名称。myc# 设置库为共享库。SHARED# 提供源文件的相对路径。native-lib.cpp )# 在NDK中查找指定预构建的库,并将路径存储在变量中。
# 因为CMake默认将系统库添加到搜索路径中,所以您只需要指定公共NDK库的名称。
# CMake验证库是否存在,并在构建完成后完成其构建。
find_library( # 设置路径变量的名称。log-lib# 指定要CMake定位的NDK库名称。log )# 指定目标库应链接的库。您可以链接多个库,例如在此构建脚本中定义的库、预构建的第三方库或系统库。
target_link_libraries( # 指定目标库。myc# 将目标库与log库(在NDK中)链接。\${log-lib} )

native-lib.cpp里面就可以写C/C++代码了

#include <jni.h>
#include <string>/*** jni静态注册native方法*/
//extern "C" {
//    JNIEXPORT jstring JNICALL Java_com_example_myc_MainActivity_stringFromJNI(JNIEnv *env, jobject /* this */) {
//        std::string hello = "Hello from C++";
//        return env->NewStringUTF(hello.c_str());
//    }
//
//    JNIEXPORT jint JNICALL Java_com_example_myc_MainActivity_intFromJNI(JNIEnv *env, jobject /* this */, jint a, jint b) {
//        return a + b;
//    }
//}
/*** jni动态注册native方法*/
extern "C" {JNIEXPORT jstring JNICALL cpp_stringFromJNI(JNIEnv *env, jobject /* this */) {std::string hello = "Hello from C++";return env->NewStringUTF(hello.c_str());}JNIEXPORT jint JNICALL cpp_intFromJNI(JNIEnv *env, jobject obj/* this */, jint a, jint b) {/*** c++ 调用java方法*/jobject m_object = env->NewGlobalRef(obj);//创建对象的本地变量jclass myClass = env->FindClass("com/example/myc/MainActivity");//找到类文件jmethodID myMethod = env->GetMethodID(myClass, "myMethod", "(Ljava/lang/String;)V");//在类文件下找到方法,第三个参数是方法的签名也就是方法的参数类型和返回类型env->CallVoidMethod(m_object, myMethod, env->NewStringUTF("c数据"));return a + b;}
}//包名+类名字符串定义:
const char *class_name = "com/example/myc/MainActivity";
// 重点:函数表,相当于绑定,如果有多个方法要动态注册,在数组里面定义即可,第一个参数是java定义的函数名,第二个是函数签名,第三个是函数指针(也就是在c++自定义的函数名)
static const JNINativeMethod methods[] = {{"stringFromJNI", "()Ljava/lang/String;", (void *) cpp_stringFromJNI},{"intFromJNI",    "(II)I",                (void *) cpp_intFromJNI},
};
// 定义注册方法
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
//    LOGD("动态注册");JNIEnv *env;if ((vm)->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
//        LOGD("动态注册GetEnv  fail");return JNI_ERR;}// 获取类引用jclass clazz = env->FindClass(class_name);// 注册native方法,sizeof(methods) 表示 methods 数组占用的总字节数,sizeof(methods[0]) 表示 methods[0] 类型占用的字节数。将这两个值相除,得到 methods 数组中元素的数量。jint register_result = env->RegisterNatives(clazz, methods,sizeof(methods) / sizeof(methods[0]));if (register_result) { // 非零true 进if
//        LOGD("动态注册 fail regist_result = %d", regist_result);} else {
//        LOGI("动态注册 success result = %d", regist_result);}return JNI_VERSION_1_6;
}void myMethod(JNIEnv *env, jobject obj) {jclass stringClass = env->FindClass("java/lang/String");jmethodID constructMethod = env->GetMethodID(stringClass, "<init>", "()V");jobject stringObj = env->NewObject(stringClass, constructMethod);std::string argStr = std::to_string(5);jstring result = (jstring) env->NewStringUTF(argStr.c_str());jobjectArray args = env->NewObjectArray(2, stringClass, stringObj);env->SetObjectArrayElement(args, 0, result);env->SetObjectArrayElement(args, 1, stringObj);
}

activity中

class MainActivity : AppCompatActivity() {private lateinit var binding: ActivityMainBindingprivate var b = 0override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)//        binding.sampleText.text = stringFromJNI()// java调用c++方法binding.sampleText.text = intFromJNI(1, b).toString()findViewById<Button>(R.id.btn_jia).setOnClickListener {binding.sampleText.text = intFromJNI(1, ++b).toString()}}/*** c++调用java方法*/fun myMethod(str:String){Toast.makeText(this,"来自c端数据=$str",Toast.LENGTH_LONG).show()}/*** java调用c++方法*/external fun stringFromJNI(): Stringexternal fun intFromJNI(a: Int, b: Int): Intcompanion object {// 导入c++库与CMakeLists中的库的命名一致init {System.loadLibrary("myc")}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1473761.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】模板进阶--保姆级解析(什么是非类型模板参数?什么是模板的特化?模板的特化如何应用?)

目录 一、前言 二、什么是C模板&#xff1f; &#x1f4a6;泛型编程的思想 &#x1f4a6;C模板的分类 三、非类型模板参数 ⚡问题引入⚡ ⚡非类型模板参数的使用⚡ &#x1f525;非类型模板参数的定义 &#x1f525;非类型模板参数的两种类型 &#x1f52…

机器学习之保存与加载

前言 模型的数据需要存储和加载&#xff0c;这节介绍存储和加载的方式方法。 存和加载模型权重 保存模型使用save_checkpoint接口&#xff0c;传入网络和指定的保存路径&#xff0c;要加载模型权重&#xff0c;需要先创建相同模型的实例&#xff0c;然后使用load_checkpoint…

大厂面试官赞不绝口的后端技术亮点【后端项目亮点合集(2)】

本文将持续更新~~ hello hello~ &#xff0c;这里是绝命Coding——老白~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#xff1a;绝命C…

Redis 中 Set 和 Zset 类型

目录 1.Set类型 1.1 Set集合 1.2 普通命令 1.3 集合操作 1.4 内部编码 1.5 使用场景 2.Zset类型 2.1 Zset有序集合 2.2 普通命令 2.3 集合间操作 2.4 内部编码 2.5 使用场景 1.Set类型 1.1 Set集合 集合类型也是保存多个字符串类型的元素&#xff0c;但是和列表类型不同的是&…

QT的编译过程(底层逻辑)

qmake -project 用于从源代码生成项目文件&#xff0c;qmake 用于从项目文件生成 Makefile&#xff0c;而 make 用于根据 Makefile 构建项目。 详细解释&#xff1a; qmake -project 这个命令用于从源代码目录生成一个初始的 Qt 项目文件&#xff08;.pro 文件&#xff09;。它…

2.1 tmux和vim

文章目录 前言概述tmuxvim总结 前言 开始学习的时间是 2024.7.6 ,13&#xff1a;47 概述 最好多使用&#xff0c;练成条件反射式的 直接使用终端的工具&#xff0c;可以连接到服务器&#xff0c;不需要使用本地的软件 tmux 这个主要有两个功能&#xff0c;第一个功能是分…

SpringBoot项目练习

文章目录 SpringBootVue后台管理系统所需软件下载、安装、版本查询Vue搭建一个简单的Vue项目 Spring项目1项目架构 SpringBootVue后台管理系统 学习视频&#xff1a; https://www.bilibili.com/video/BV1U44y1W77D/?spm_id_from333.337.search-card.all.click&vd_sourcec…

2024年最新运维面试题(附答案)

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆云计算学堂 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ 一&#xff0e;选择题 1.HTTP协议默认使用哪个端口…

【刷题汇总--大数加法、 链表相加(二)、大数乘法】

C日常刷题积累 今日刷题汇总 - day0061、大数加法1.1、题目1.2、思路1.3、程序实现 2、 链表相加(二)2.1、题目2.2、思路2.3、程序实现 3、大数乘法3.1、题目3.2、思路3.3、程序实现 4、题目链接 今日刷题汇总 - day006 1、大数加法 1.1、题目 1.2、思路 读完题,明白大数相加…

最新版情侣飞行棋dofm,已解锁高阶私密模式,单身狗务必绕道!(附深夜学习资源)

今天阿星要跟大家聊一款让阿星这个大老爷们儿面红耳赤的神奇游戏——情侣飞行棋。它的神奇之处就在于专为情侣设计&#xff0c;能让情侣之间感情迅速升温&#xff0c;但单身狗们请自觉绕道&#xff0c;不然后果自负哦&#xff01; 打开游戏&#xff0c;界面清新&#xff0c;操…

平价猫粮新选择!福派斯鲜肉猫粮,让猫咪享受美味大餐!

福派斯鲜肉猫粮&#xff0c;作为一款备受铲屎官们青睐的猫粮品牌&#xff0c;凭借其卓越的品质和高性价比&#xff0c;为众多猫主带来了健康与美味的双重享受。接下来&#xff0c;我们将从多个维度对这款猫粮进行解析&#xff0c;让各位铲屎官更加全面地了解它的魅力所在。 1️…

11.x86游戏实战-汇编指令add sub inc dec

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 上一个内容&#xff1a;10.x86游戏实战-汇编指令lea 首先双击下图红框位置 然后在下图红框位置输入0 然…

电商视角如何理解动态IP与静态IP

在电子商务的蓬勃发展中&#xff0c;网络基础设施的稳定性和安全性是至关重要的。其中&#xff0c;IP地址作为网络设备间通信的基础&#xff0c;扮演着举足轻重的角色。从电商的视角出发&#xff0c;我们可以将动态IP和静态IP比作电商平台上不同类型的店铺安排&#xff0c;以此…

记录一次MySQL恢复

一、前言 此文章由一次数据库被黑客删除而引发 由于对于Linux操作、docker使用、MySQL原理这些都相对不是很熟悉&#xff0c;所以记录下来避免以后在工作中遇到类似的问题而惊慌失措。 1.MySQL环境现状 docker管理的&#xff0c;8.0.26版本 启动语句: docker run -d -p 33…

智慧矿山建设规划方案(121页Word)

智慧矿山建设项目方案摘要 一、项目背景及现状分析 项目背景 随着信息技术的迅猛发展&#xff0c;智慧化、数字化已成为矿山行业转型升级的必然趋势。智慧矿山建设项目旨在通过集成先进的信息技术手段&#xff0c;实现对矿山生产、管理、安全等全过程的智能化监控与管理&…

【ARMv8/v9 GIC 系列 1.5 -- Enabling the distribution of interrupts】

请阅读【ARM GICv3/v4 实战学习 】 文章目录 Enabling the distribution of interruptsGIC Distributor 中断组分发控制CPU Interface 中断组分发控制Physical LPIs 的启用Summary Enabling the distribution of interrupts 在ARM GICv3和GICv4体系结构中&#xff0c;中断分发…

如何搭建Ubuntu环境安装禅道

一、禅道安装部署的环境要求 禅道安装部署环境推荐使用 Linux Apache PHP7.0以上版本 MySQL5.5以上版本/MariaDB的组合。Nginx其次&#xff0c;不推荐IIS PHP组合。禅道需要使用PHP的这些扩展&#xff1a;pdo、pdo_mysql、json、filte、openssl、mbstring、zlib、curl、gd、…

DP:二维费用背包问题

文章目录 &#x1f3b5;二维费用背包问题&#x1f3b6;引言&#x1f3b6;问题定义&#x1f3b6;动态规划思想&#x1f3b6;状态定义和状态转移方程&#x1f3b6;初始条件和边界情况 &#x1f3b5;例题&#x1f3b6;1.一和零&#x1f3b6;2.盈利计划 &#x1f3b5;总结 &#x1…

OpenAI突然停止中国API使用,出海SaaS产品如何化挑战为机遇?

2023年是AI爆发的年代&#xff0c;人工智能带来的信息裂变刷新了整个SaaS行业。在这个AI引领的时代&#xff0c;我们不应该单纯依赖工具本身&#xff0c;而是要理解如何将这些AI功能与行业相结合。 然而&#xff0c;上周OpenAI宣布禁止对中国提供API服务&#xff0c;有一些用户…

基于Transformer神经网络的锂离子电池剩余使用寿命估计MATLAB实现【NASA电池数据集】

Transformer神经网络 基于Transformer神经网络的锂离子电池剩余使用寿命估计是一种先进的方法&#xff0c;它利用了Transformer模型在处理序列数据方面的优势。 Transformer能够有效地捕捉时间序列中的长程依赖关系和非线性模式&#xff0c;相比传统的基于循环神经网络&…