JNI中基本类型数组的传递方法(无需拷贝数据!!!)

来源:互联网 发布:mac number 格式刷 编辑:程序博客网 时间:2024/06/14 13:37

JNI中基本类型数组的传递方法(无需拷贝数据!!!)

    博客分类: 
  • C++
  • Java
  • JNI
 
0、先来看一下主要用到哪些函数: 
C++代码  收藏代码
  1. GetIntArrayElements();//貌似得到的是副本,要拷贝数据  
  2. ReleaseIntArrayElements();//对应上面的函数的释放资源的函数  
  3. env->GetPrimitiveArrayCritical();//貌似得到的是指向原数据的指针  
  4. env->ReleasePrimitiveArrayCritical();////对应上面的函数的释放资源的函数  

官方文档:http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp17440 
JNI函数的中译本(貌似没看到GetPrimitiveArrayCritical()):http://blog.csdn.net/qinjuning 



下面正式开始: 

1、不知道如何设置JNI环境的先看这里: 
http://cherishlc.iteye.com/blog/1328136 

2、Java端程序: 
Java端: 
Java代码  收藏代码
  1. package tests;  
  2.   
  3. import java.util.Arrays;  
  4.   
  5. public class TestJNIArray {  
  6.     static{  
  7.         System.loadLibrary("TestJNIArray");  
  8.     }  
  9.       
  10.     public static native void addOne(int[] ints);//数组元素+1  
  11.     public static native void addOne(double[] ints);//数组元素+1,为了测试,C++中循环了5次  
  12.     public static native int[] getNewArray(int size,int initValue);//生成初始值为initValue的数组,数组长度为size  
  13.       
  14.     public static void main(String[] args) throws InterruptedException {  
  15.         int n=20;  
  16.           
  17.         final int[] a=new int[n];  
  18.           
  19.         for (int i = 0; i < a.length; i++) {  
  20.             a[i]=i;  
  21.         }  
  22.         if(n<50)System.out.println(Arrays.toString(a));  
  23.         addOne(a);  
  24.         if(n<50)System.out.println(Arrays.toString(a));  
  25.           
  26.           
  27.         final double d[]=new double[n];  
  28.         for (int i = 0; i < d.length; i++) {  
  29.             d[i]=i;  
  30.         }  
  31.         //addOne(d);  
  32.         if(n<50)System.out.println(Arrays.toString(d));  
  33.           
  34.           
  35.         new Thread(new Runnable() {  
  36.               
  37.             @Override  
  38.             public void run() {  
  39.                 addOne(d);  
  40.                   
  41.             }  
  42.         }).start();  
  43.         for (int i = 0; i < 200; i++) {  
  44.             Thread.sleep(20);  
  45.             System.out.println(Arrays.toString(d));  
  46.             if(d[d.length-1]-d[0]!=n-1)System.out.println("检测到C++端更新数据中");//看看能否找到在C++更新数组时Java端又读取数据的情况  
  47.         }  
  48.           
  49.           
  50.         int[] b=getNewArray(29);  
  51.         System.out.println(Arrays.toString(b));  
  52.           
  53.           
  54.         int[] c=getNewArray(09);  
  55.         System.out.println(Arrays.toString(c));  
  56.           
  57.     }  
  58. }  


3、C++端程序: 
C++代码  收藏代码
  1. #include "tests_TestJNIArray.h"  
  2. #include <windows.h>  
  3.   
  4. #include <time.h>  
  5. #include <iostream>  
  6. #include <string>  
  7.   
  8. class Timer{  
  9. private:  
  10.     clock_t time;  
  11. public:  
  12.     Timer(){  
  13.         time=clock();  
  14.     }  
  15.   
  16.     clock_t getElapsedTime(){  
  17.         return clock()-time;  
  18.     }  
  19.   
  20.     clock_t getElapsedTimeAndRestart(){  
  21.         clock_t tmp=time;  
  22.         time=clock();  
  23.         return time-tmp;  
  24.     }  
  25.   
  26.     void restart(){  
  27.         time=clock();  
  28.     }  
  29.   
  30.     int getCLOCKS_PER_SEC(){  
  31.         return CLOCKS_PER_SEC;  
  32.     }  
  33. };  
  34.   
  35. JNIEXPORT void JNICALL Java_tests_TestJNIArray_addOne___3I( JNIEnv * env, jclass, jintArray intArray) {  
  36.     jboolean b;  
  37.   
  38.     Timer timer;  
  39.     jint* pint=env->GetIntArrayElements(intArray,&b);//获取指针!!第二个参数可为NULL  
  40.     std::string str=b?"true":"false";  
  41.     long t=timer.getElapsedTimeAndRestart();  
  42.     std::cout<<"GetIntArrayElements()耗时: "<<t<<"\t为副本?"<<str<<std::endl;//很悲剧,自己得到的是副本(copy了一份,速度慢啊)  
  43.     jsize size=env->GetArrayLength(intArray);  
  44.   
  45.     for (int i=0; i<size; i++)  
  46.         pint[i]+=1;  
  47.     env->ReleaseIntArrayElements(intArray,pint,0);//释放~~~  
  48.     //  对于最后一个参数(如果指针指向的数组为副本时,否则该参数不起作用)  
  49.     //      0       copy back the content and free the elems buffer  
  50.     //      JNI_COMMIT      copy back the content but do not free the elems buffer  
  51.     //      JNI_ABORT       free the buffer without copying back the possible changes  
  52.   
  53.     std::cout<<"从c++程序返回~"<<std::endl;  
  54.   
  55.   
  56. }  
  57.   
  58. JNIEXPORT void JNICALL Java_tests_TestJNIArray_addOne___3D( JNIEnv * env, jclass, jdoubleArray intArray)  
  59. {  
  60.     jboolean b;  
  61.     Timer timer;  
  62.     double* pd=(double*)env->GetPrimitiveArrayCritical(intArray,&b);  
  63.     //if(pd==NULL)return;理论上应该检查!!!!  
  64.     long t=timer.getElapsedTimeAndRestart();  
  65.     jsize size=env->GetArrayLength(intArray);  
  66.     std::string str=b?"true":"false";  
  67.     std::cout<<"GetPrimitiveArrayCritical()耗时: "<<t<<"\t为副本?"<<str<<std::endl;//这次是原始数据了,happy啊!!!  
  68.   
  69.     for(int j=0;j<5;j++){ //验证一下,Java中的数据也在更新!!!  
  70.         Sleep(1000);  
  71.     for (int i=0; i<size; i++){  
  72.         pd[i]+=1;  
  73.         Sleep(10);    
  74.     }  
  75.     }  
  76.     env->ReleasePrimitiveArrayCritical(intArray,pd,0);//别忘了释放~~~虽然不知道不释放有什么问题。。。  
  77.   
  78.     std::cout<<"从c++程序返回~"<<std::endl;  
  79. }  
  80.   
  81. JNIEXPORT jintArray JNICALL Java_tests_TestJNIArray_getNewArray( JNIEnv * env, jclass, jint size, jint initValue ) {  
  82.     jintArray intArray= env->NewIntArray(size);  
  83.     jboolean* pb;  
  84.     //jint* pint=env->GetIntArrayElements(intArray,pb);  
  85.   
  86.     jint* pint=new jint[size];  
  87.   
  88.     std::string str=*pb?"true":"false";  
  89.     std::cout<<"自己生成的Java数组,取出指针,为副本?"<<str<<std::endl;  
  90.   
  91.     for (int i=0; i<size; i++) {  
  92.         pint[i]=initValue;  
  93.     }  
  94.     env->ReleaseIntArrayElements(intArray,pint,JNI_COMMIT);  
  95.     delete []pint; //如果使用GetIntArrayElements()得到该指针则不可以!!!否则Java直接崩溃了  
  96.     return intArray;  
  97. }  
原创粉丝点击