JNI中修改(基本类型)参数并返回到Java层使用
最近在JNI相关项目中遇到一个问题:在Java层传入多个int类型的参数,在jni层修改参数值或地址之后重新返回到Java层。这应该算是基本知识了,尤其是基本类型的参数往往看似简单,所以在之前学习jni时就一笔带过了,结果现在突然遇到这个问题竟然需要再查找资料学习,因此这周在重新复习一遍基础知识之后将此记录一下。走的再远,也不要忘记脚底的路。
还是用Demo来解释下需求和对应解决方案吧
public class LibraryManager {
static{
System.loadLibrary("libtest");
}
public final static native int add1(int arg1, int arg2, int result);
public final static native int add2(int arg1, int arg2, int result);
}
在Java层写了两个方法分别模拟这个需求,在底层对arg1和arg2参数做操作,之后将结果存入result中,希望能在Java层使用result,至于方法的返回值,则是模拟表示方法执行成功与否的标志位。
下面分别在jni中用两种方式实现该需求,当然这两种都是典型错误的。
JNIEXPORT jint JNICALL Java_com_xxx_LibraryManager_add1(
JNIEnv *jenv, jclass jcls, jint jarg1, jint jarg2, jint jarg3){
jarg3=jarg1+jarg2;
LOGI("add1 arg3=%d", jarg3);
return ;
} JNIEXPORT jint JNICALL Java_com_xxx_LibraryManager_add2(
JNIEnv *jenv, jclass jcls, jint jarg1, jint jarg2, jint *jarg3){
int result=jarg1+jarg2;
jarg3=&result;
LOGI("add2 arg3=%d", *jarg3);
return ;
}
如果还记得jni的运行原理的话,应该很容易理解这么写只是修改在c线程里边的参数值(add1()中)和参数地址(add2()中),至于Java层对应的参数没有变化,也就是说jni中的基本类型作为参数时只是形参传入的,对于上层没有任何影响。当然如果作为return值的话是绝对可以的,但是现在讨论的是作为参数值的方法。那么还是这个需求,应该怎么解决呢?
在LibraryManager.class中增加两个新的方法
public final static native int addConfirm1(int arg1, int arg2, int[] result);
public final static native int addConfirm2(int arg1, int arg2, Integer result);
看第三个参数就能知道解决方法了,将int类型转换为int[](addConfirm1()中)和int对应的整型类(addConfirm2()中),当然就是使用jni中的JNIEnv可以获取到的方法来修改参数,至于具体用法在下面详细列出。
JNIEXPORT jint JNICALL Java_com_bob_testlib_LibraryManager_addConfirm1(
JNIEnv *jenv, jclass jcls, jint jarg1, jint jarg2, jintArray jarg3){
int result=jarg1+jarg2;
int *arg3 = jenv->GetIntArrayElements(jarg3, );
*arg3=result;
jenv->ReleaseIntArrayElements(jarg3, arg3, );
return ;
}
JNIEXPORT jint JNICALL Java_com_bob_testlib_LibraryManager_addConfirm2(
JNIEnv *jenv, jclass jcls, jint jarg1, jint jarg2, jobject jarg3){
int result=jarg1+jarg2;
jclass intClass = jenv->FindClass("java/lang/Integer");
jfieldID intId = jenv->GetFieldID(intClass, "value", "I");
jenv->SetIntField(jarg3, intId, result);
return ;
}
在addConfirm1()中将int[]的参数传入,这样可以通过JNIEnv的GetIntArrayElements()获取到传入参数的地址并绑定到int*变量中,在修改变量之后,通过ReleaseIntArrayElements()通过第三个参数mode=0更新Java层jintArray的参数,并释放JNI层的int*变量。
在addConfirm2()中将jobject参数传入,通过JNIEnv的FindClass()找到Java层Integer类对应jni层的jclass,再根据jclass通过JNIEnv的GetFiledID()找到Java层Integer类的value对应jni层的jclass的jfieldID,最后通过JNIEnv的SetIntField()将要更新的int值存入到Java层的jobject中即可。这个流程就是把Java层的Integer看成自定义的类,之后就是更新自定义类中的变量。
目前能想到的有上面两种方式可以解决类似需求,其思想都是将Java中的基本类型转变成Java类,之后再用JNI中对类的操作方法进行修改。
JNI中修改(基本类型)参数并返回到Java层使用的更多相关文章
- 在Rancher中修改K8S服务参数的万金油法则
作者简介 王海龙,Rancher中国社区技术经理,负责Rancher中国技术社区的维护和运营.拥有7年的云计算领域经验,经历了OpenStack到Kubernetes的技术变革,无论底层操作系统Lin ...
- curl中通过json格式吧post值返回到java中遇到中文乱码的问题
首先是: curl中模拟http请求: curl -l 127.0.0.1:8080/spacobj/core/do?acid=100 -H "token:101hh" -H &q ...
- Base64编解码Android和ios的例子,补充JNI中的例子
1.在Android中java层提供了工具类:android.util.Base64; 里面都是静态方法,方便直接使用: 使用方法如下: // Base64 编码: byte [] encode = ...
- Java层与Jni层的数组传递(转)
源:Java层与Jni层的数组传递 Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是Java层把需要发送给客户端的数据流传递到Jni层,由Jni层的S ...
- Android开发实践:Java层与Jni层的数组传递
转载:http://www.linuxidc.com/Linux/2014-03/97561.htm Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是 ...
- JNI中的内存管理(转)
源:JNI中的内存管理 JNI 编程简介 JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互 ...
- Java Native Interface 二 JNI中对Java基本类型和引用类型的处理
本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 Java编程里会使用到两种类型:基本类型(如 ...
- java 修改HttpServletRequest的参数或请求头
场景:过滤器中获取参数Token并添加到请求头(用户认证兼容老系统) 请求头和请求参数是不能直接修改,也没有提供修改的方法,但是可以在过滤器和拦截器中使用HttpServletRequestWrapp ...
- Android Multimedia框架总结(四)MediaPlayer中从Java层到C++层类关系及prepare及之后其他过程
转载请把头部出处链接和尾部二维码一起转载,本文出自:http://blog.csdn.net/hejjunlin/article/details/52420803 前言:在上篇中,分析了MediaPl ...
随机推荐
- ELK-7.3安装部署
原文 ELK-7.3安装部署 前沿 1.什么是ELK? ELK是由Elasticsearch.Logstash.Kibana 三个开源软件的组成的一个组合体 不懂自行查阅 https://www.el ...
- C#冒泡排序法学习
一,冒泡排序法理解:就是将一个集合里的数据当前位置和后一位比较,然当前位置大于后一位,则两个位置替换,直到排序完成 using System; using System.Collections.Gen ...
- Spring学习笔记(13)——aop原理及拦截器
原理 AOP(Aspect Oriented Programming),也就是面向方面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP将应用系统分为两部分,核心业务逻辑(Core bu ...
- LeetCode Linked List Medium 2. Add Two Numbers
Description You are given two non-empty linked lists representing two non-negative integers. The dig ...
- runtime之归档和解档
IOS开发之NSCoding协议(使用runtime)近期学习IOS的runtime库,然后看到之前写的NSCoding协议有点复杂,如果属性少还好,如果100多个属性,则会显得麻烦.下面使用常规方式 ...
- nginx 反向代理服务
目录 Nginx代理服务基本概述 Nginx代理服务常见模式 Nginx代理服务支持协议 Nginx反向代理配置语法 Nginx反向代理场景实践 配置代理实战 在lb01上安装nginx Nginx代 ...
- redis笔记3-命令
通用命令:keys * --查询所有keykeys list* --查询list开头的keytype key1 --查询键对应的value类型del key --删除指定的keyttl key --查 ...
- 【串线篇】SpringMvc视图解析
一. 请求处理方法执行完成后,最终返回一个 ModelAndView 对象.对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个 ...
- bean的初始化和销毁方法
1.bean的生命周期: bean创建---初始化----销毁的过程 容器管理bean的生命周期: 我们可以自定义初始化和销毁方法:容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁 ...
- hdu 3060 Area2 (计算几何模板)
Problem Description 小白最近又被空军特招为飞行员,参与一项实战演习.演习的内容还是轰炸某个岛屿(这次的岛屿很大,很大很大很大,大到炸弹怎么扔都能完全在岛屿上引爆),看来小白确实是飞 ...