最近在JNI相关项目中遇到一个问题:在Java层传入多个int类型的参数,在jni层修改参数值或地址之后重新返回到Java层。这应该算是基本知识了,尤其是基本类型的参数往往看似简单,所以在之前学习jni时就一笔带过了,结果现在突然遇到这个问题竟然需要再查找资料学习,因此这周在重新复习一遍基础知识之后将此记录一下。走的再远,也不要忘记脚底的路。
还是用Demo来解释下需求和对应解决方案吧
1 public class libraryManager { 2 3 static{ 4 System.loadlibrary("libtest"); 5 } 6 7 final static native int add1(int arg1,int arg2,1)">int result); 8 int add2( 9 12 }
在Java层写了两个方法分别模拟这个需求,在底层对arg1和arg2参数做 *** 作,之后将结果存入result中,希望能在Java层使用result,至于方法的返回值,则是模拟表示方法执行成功与否的标志位。
下面分别在jni中用两种方式实现该需求,当然这两种都是典型错误的。
JNIEXPORT jint JNICALL Java_com_xxx_libraryManager_add1( 2 jnienv *jenv,jclass jcls,jint jarg1,jint jarg2,jint jarg3){ 3 jarg3=jarg1+jarg2; 4 LOGI("add1 arg3=%d",jarg3); 5 return 1; 6 } 7 8 JNIEXPORT jint JNICALL Java_com_xxx_libraryManager_add2( 9 jnienv *jenv,jint *jarg3){10 int result=jarg1+11 jarg3=&result;12 LOGI(add2 arg3=%d",*jarg3);13 214 }
如果还记得jni的运行原理的话,应该很容易理解这么写只是修改在c线程里边的参数值(add1()中)和参数地址(add2()中),至于Java层对应的参数没有变化,也就是说jni中的基本类型作为参数时只是形参传入的,对于上层没有任何影响。当然如果作为return值的话是绝对可以的,但是现在讨论的是作为参数值的方法。那么还是这个需求,应该怎么解决呢?
在libraryManager.class中增加两个新的方法
1 int addConfirm1([] result);2 int addConfirm2(int类型转换为int[](addConfirm1()中)和int对应的整型类(addConfirm2()中),当然就是使用jni中的jnienv可以获取到的方法来修改参数,至于具体用法在下面详细列出。JNIEXPORT jint JNICALL Java_com_bob_testlib_libraryManager_addConfirm1( 4 int *arg3 = jenv->GetIntArrayElements(jarg3,0 5 *arg3= 6 jenv->ReleaseIntArrayElements(jarg3,arg3,1)">3 9 JNIEXPORT jint JNICALL Java_com_bob_testlib_libraryManager_addConfirm2(10 jnienv *11 12 jclass intClass = jenv->FindClass(java/lang/Integer13 jfIEldID intID = jenv->GetFIEldID(intClass,1)">valueI14 jenv->SetIntFIEld(jarg3,intID,result);15 416 }
在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层使用全部内容,希望文章能够帮你解决JNI中修改(基本类型)参数并返回到Java层使用所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)