• JNI数组操作


    Java中数组分为两种:

    1.基本类型数组

    2.对象类型(Object[])的数组(数组中存放的是指向Java对象中的引用)

    一个能通用于两种不同类型数组的函数:

    GetArrayLength(jarray array);

    首先来看一下怎么处理基本类型的数组:

    (1) GetArrayElements(Array arr , jboolean* isCopide);

    这类函数可以把Java基本类型的数组转换到C/C++中的数组,有两种处理方式,一种是拷贝一份传回本地代码,另一个是把指向Java数组的指针直接传回到本地代码中,处理完本地化的数组后,通过ReleaseArrayElements来释放数组

    (2) ReleaseArrayElements(Array arr , * array , jint mode)

    用这个函数可以选择将如何处理Java跟C++的数组,是提交,还是撤销等,内存释放还是不释放等

    mode可以取下面的值:

    0 :对Java的数组进行更新并释放C/C++的数组

    JNI_COMMIT :对Java的数组进行更新但是不释放C/C++的数组

    JNI_ABORT:对Java的数组不进行更新,释放C/C++的数组

    (3) GetPrimittiveArrayCritical(jarray arr , jboolean* isCopied);

    (4) ReleasePrimitiveArrayCritical(jarray arr , void* array , jint mode);

    也是JDK1.2出来的,为了增加直接传回指向Java数组的指针而加入的函数,同样的也会有同GetStringCritical的死锁的问题

    (5) GetArrayRegion(Array arr , jsize start , jsize len , * buffer);

    在C/C++预先开辟一段内存,然后把Java基本类型的数组拷贝到这段内存中,这个方法和之前拷贝字符串的GetStringRegion方法的原理是类似的

    (6) SetArrayRegion(Array arr , jsize start , jsize len , const * buffer);

    把Java基本类型的数组中的指定范围的元素用C/C++的数组中的元素来赋值

    (7) Array NewArray(jsize sz)

    指定一个长度然后返回相应的Java基本类型的数组

    在来看一下怎么处理对象型数组

    JNI没有提供直接把Java的对象类型数组(Object[])直接转到C++中的Object[]数组的函数,而是直接通过Get/SetObjectArrayElement这样的函数来对Java的Object[]数组进行操作由于去的对象数组没有进行拷贝,所以不需要释放任何资源

    NewObjectArray可以通过指定长度跟初始值来创建某个类的数组

    下面来看一下例子:操作两种类型的数组

    Java中的代码:

    [java] view plaincopy在CODE上查看代码片派生到我的代码片

      1. package com.jni.demo;
      2. public class JNIDemo {
      3. //定义一个int型数组
      4. int[] arrays = {4,3,12,56,1,23,45,67};
      5. //定义Father对象数组
      6. Father[] objArrays = {new Father(),new Father(),new Father()};
      7. //定义一个本地方法
      8. public native void callCppFunction();
      9. public static void main(String[] args)throws Exception{
      10. //调用动态链接库
      11. System.loadLibrary("JNIDemo");
      12. JNIDemo jniDemo = new JNIDemo();
      13. jniDemo.callCppFunction();
      14. }
      15. }

      16. C++中的代码: [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
        1. #include
        2. #include"com_jni_demo_JNIDemo.h"
        3. #include
        4. using namespace std;
        5. JNIEXPORT void JNICALL Java_com_jni_demo_JNIDemo_callCppFunction (JNIEnv * env, jobject obj)
        6. {
        7. //获取Java中数组属性arrays的id
        8. jfieldID fid_arrays = env->GetFieldID(env->GetObjectClass(obj),"arrays","[I");
        9. //获取Java中数组属性arrays的对象
        10. jintArray jint_arr = (jintArray)env->GetObjectField(obj,fid_arrays);
        11. //获取arrays对象的指针
        12. jint* int_arr = env->GetIntArrayElements(jint_arr,NULL);
        13. //获取数组的长度
        14. jsize len = env->GetArrayLength(jint_arr);
        15. //打印数组中的值
        16. cout<<"数组的值为:";
        17. for(int s =0;s<len;s++){ <li="" class="alt"> cout<<int_arr[s]<<','; <li=""> }
        18. cout<<endl; <li="">
        19. //新建一个jintArray对象
        20. jintArray jint_arr_temp = env->NewIntArray(len);
        21. //获取jint_arr_temp对象的指针
        22. jint* int_arr_temp = env->GetIntArrayElements(jint_arr_temp,NULL);
        23. //计数
        24. jint count = 0;
        25. //偶数位存入到int_arr_temp内存中
        26. for(jsize j=0;j<len;j++){ <li="" class="alt"> if(j%2==0){
        27. int_arr_temp[count++] = int_arr[j];
        28. }
        29. }
        30. //打印int_arr_temp内存中的数组
        31. cout<<"数组中位置是偶数的值为:";
        32. for(jsize k=0;k<count;k++){ <li=""> cout<<int_arr_temp[k]<<','; <li="" class="alt"> }
        33. cout<<endl; <li="" class="alt">
        34. //将数组中一段(0-2)数据拷贝到内存中,并且打印出来
        35. jint* buffer = new jint[len];
        36. //获取数组中从0开始长度为3的一段数据值
        37. env->GetIntArrayRegion(jint_arr,0,3,buffer);
        38. cout<<"打印数组中0-3一段值:";
        39. for(int l=0;l<3;l++){
        40. cout<<buffer[l]<<','; <li="" class="alt"> }
        41. cout<<endl; <li="" class="alt">
        42. //将数组中的一段(3-7)设置成一定的值,并且打印出来
        43. jint* buffers = new jint[4];
        44. for(int n=0;n<4;n++){
        45. buffers[n] = n+1;
        46. }
        47. //将buffers这个数组中值设置到数组从3开始长度是4的值中
        48. env->SetIntArrayRegion(jint_arr,3,4,buffers);
        49. //从新获取数组指针
        50. int_arr = env->GetIntArrayElements(jint_arr,NULL);
        51. cout<<"数组中3-7这段的值变成了:";
        52. for(int m=0;m<len;m++){ <li="" class="alt"> cout<<int_arr[m]<<','; <li=""> }
        53. cout<<endl; <li="">
        54. //调用C++标准库中的排序方法sort(...),传递一个数组的开始指针和结束指针
        55. std::sort(int_arr,int_arr+len);
        56. //迭代打印数组中的元素
        57. cout<<"数组排序后的结果:";
        58. for(jsize i=0;i<len;i++){ <li=""> cout<<int_arr[i]<<','; <li="" class="alt"> }
        59. cout<<endl; <li="" class="alt"> //释放数组指针
        60. env->ReleaseIntArrayElements(jint_arr,int_arr,JNI_ABORT);
        61. //获取Java中对象Father数组属性的id
        62. jfieldID fid_obj_arrays = env->GetFieldID(env->GetObjectClass(obj),"objArrays","[Lcom/jni/demo/Father;");
        63. //获取Java中对象数组Father属性objArrays的对象
        64. jobjectArray jobj_arr = (jobjectArray)env->GetObjectField(obj,fid_obj_arrays);
        65. //从对象数组中获取索引值为1的对象Father
        66. jobject jobj = env->GetObjectArrayElement(jobj_arr,1);
        67. //获取Father对象的class对象
        68. jclass clazz_father = env->GetObjectClass(jobj);
        69. //获取Father对象中的function方法的id
        70. jmethodID id_father_function = env->GetMethodID(clazz_father,"function","()V");
        71. //调用Father对象中的function方法
        72. env->CallVoidMethod(jobj,id_father_function);
        73. //在本地创建一个大小为10的对象数组,对象的初始化都是jobj,也就是方法的第三个参数
        74. jobjectArray jobj_arr_temp = env->NewObjectArray(10,env->GetObjectClass(jobj),jobj);
        75. //获取本地对象数组中第4个对象
        76. jobject jobj_temp = env->GetObjectArrayElement(jobj_arr_temp,3);
        77. //调用Father对象中的function方法
        78. env->CallVoidMethod(jobj_temp,id_father_function);
        79. }

        80. 在Eclipse编译运行结果如下:

          不要以为这就结束了,后面还有很多内容呀!

  • 相关阅读:
    实验四 数据库安全设计
    对订单数据库进行查询等操作
    vue学习笔记7 -组件之 父子组件之间的访问
    vue学习笔记6 父子组件的通信之 子组件修改由父组件传递过来的值 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed pro
    vue学习笔记5 组件
    vue学习笔记4 v-mode
    vue学习笔记3 购物车 实例
    vue学习笔记2 实例学习
    vue学习笔记1 《Vue.js 前端开发 快速入门与专业应用》
    postman学习:如何写断言
  • 原文地址:https://www.cnblogs.com/cy1993/p/11083509.html
Copyright © 2020-2023  润新知