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 ...
随机推荐
- 64.二叉搜索树的第K个节点
题目描述: 给定一棵二叉搜索树,请找出其中的第k小的结点.例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4. 思路分析: 根据二叉搜索树的特殊性,我们中序遍历它 ...
- SpringMVC学习(2):经典的HelloWorld实现
前一篇简单介绍了Spring MVC的一些知识,下面就要开始学习如何把Spring MVC运用到具体的项目中去. 首先还是从一个简单的Hello World项目说起: 我机器的开发环境为: Ubunt ...
- 错误提示:Wrong Local header signature: 0xE011CFD0
导入Excel时出现错误,错误提示:Wrong Local header signature: 0xE011CFD0,这个是excel的扩展名问题,.xlsx 应该XSSFWorkbook work ...
- element checkbox 勾选时出现弹框提示。
复选框选中的时候,必须提示是否确定选中,取消勾选的时候也要. 不能解决的思路: 1.element的checkbox只有一个change事件,该事件只返回该选项最新的值(true,false)(不会返 ...
- 深入学习Redis持久化
一.Redis高可用概述 在介绍Redis高可用之前,先说明一下在Redis的语境中高可用的含义. 我们知道,在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常 ...
- 【Java学习笔记】2015.1.5
1.classpath中的“.”表示当前的路径,所以配置classpath时要注意不能忘了“.”.如果不注意,会出现cmd下运行程序时,.java文件可以编译但是不能运行: 一般的classpath配 ...
- Kaggle数据集下载
Kaggle数据集下载步骤: 安装Kaggle库: 注册Kaggle账户: 找到数据集,接受rules: 在My Account>>API中,点击Create New API Token, ...
- JavaSE---Object
1.概述 Object常用方法: 1.1 getClass(): public final native Class<?> getClass(); 返回 该对象 运行时的Class ...
- 原生js和jquery
$(document).ready(function() {//jquery的写法 }); (function () { //原生js的写法 })();
- 【Flutter学习】可滚动组件之SingleChildScrollView
一,概述 SingleChildScrollView类似于Android中的ScrollView,它只能接收一个子Widget.定义如下: 二,构造函数 const SingleChildScroll ...