2 通过JNI混合使用Java和C++ -----> 访问数组

关于c和cpp实现native方法的一些注释:

1>  在jni.h中首先定义了C的实现方式,然后用内联函数实现了Cpp的实现方式,如下所示:

const char* GetStringUTFChars(jstring str, jboolean *isCopy)   /* 依赖于C方式实现Cpp */

{

  return functions->GetStringUTFChars(this,str,isCopy);       /* C实现方式 */

}

因此,在C中可能这样写:(*env)->GetStringUTFChars(env, str, NULL); 但在CPP中,我们必须这么写:env->GetStringUTFChars(str, NULL);

有两个主要区别:

首先 ---> cpp函数不包含参数JNIEnv* env;

其次 ---> 在cpp实现中,env直接指向包含JNI函数指针的函数表,而在c实现中,env只是指向某个位置,而该位置才包含一个指向函数表的指针,因此必须使用(*env)才能调用JNI函数。

/* jni.h中JNIEnv的定义 */

#ifdef __cplusplus

typedef JNIEnv_ JNIEnv;                                 /* cpp定义 */

#else

typedef const struct JNINativeInterface_ *JNIEnv;       /* c定义 */

#endif

 

2>  关于动态库的编译:

如果使用.c文件生成动态库,则使用gcc编译:

gcc -Wl,--kill-at –shared –I D:jdk1.7.0_75include –I D:jdk1.7.0_75includewin32 IntArray.c –o intarray.dll

如果使用.cpp文件生成动态库,则使用g++编译:

g++ -Wl,--kill-at –shared –I D:jdk1.7.0_75include –I D:jdk1.7.0_75includewin32 ObjectArrayTest.cpp –o objectarraytest.dll

JNI访问基本数组时与访问字符串类似,而且可以通过JNI函数SetIntArrayRegion改变基本数组的值。此外,JNI提供了一系列的Get/Release<Type>ArrayElements函数来操作基本数组,其返回/释放一个指向(元素本身或其副本)的指针,具体实现由JVM决定,比较安全,如下程序通过native方法计算int型数组的和:

 1 // IntArray.java
 2 class IntArray
 3 {
 4     static
 5     {
 6         System.loadLibrary("intarray");
 7     }
 8     private native int SumArray(int[] arr);
 9     
10     public static void main(String[] args)
11     {
12         IntArray p = new IntArray();
13         int arr[] = new int[10];
14         for(int i = 0; i < 10; i++)
15         {
16             arr[i] = i;
17         }
18         int sum = p.SumArray(arr);
19         System.out.println("sum = " + sum);
20     }
21 }
22 
23 /***********************************************/
24 // Intarray.h
25 /* DO NOT EDIT THIS FILE - it is machine generated */
26 #include <jni.h>
27 /* Header for class IntArray */
28 
29 #ifndef _Included_IntArray
30 #define _Included_IntArray
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 /*
35  * Class:     IntArray
36  * Method:    SumArray
37  * Signature: ([I)I
38  */
39 JNIEXPORT jint JNICALL Java_IntArray_SumArray
40   (JNIEnv *, jobject, jintArray);
41 
42 #ifdef __cplusplus
43 }
44 #endif
45 #endif
46 
47 /***********************************************/
48 // IntArray.c
49 #include "IntArray.h"
50 
51 JNIEXPORT jint JNICALL Java_IntArray_SumArray
52   (JNIEnv *env, jobject obj, jintArray arr)
53   {
54       jint buf[10];
55       jint i, sum = 0;
56       (*env)->GetIntArrayRegion(env, arr, 0, 10, buf);
57       for(i = 0; i < 10; i++)
58       {
59           sum += buf[i];
60       }
61       return sum;
62   }

JNI访问对象数组时使用函数对:Get/SetObjectArrayElement返回/更新指定索引的对象,如下native方法返回一个5*5的二维数组:

 1 //ObjectArrayTest.java
 2 class ObjectArrayTest
 3 {
 4     static
 5     {
 6         System.loadLibrary("objectarraytest");
 7     }
 8     private static native int[][] InitInt2DArray(int size);
 9     
10     public static void main(String[] args)
11     {
12         int[][] int2DArr = InitInt2DArray(5);
13         for(int i = 0; i < 5; i++)
14         {
15             for(int j = 0; j < 5; j++)
16             {
17                 System.out.println(int2DArr + "  ");
18             }
19             System.out.println();
20         }        
21     }
22 }
23 
24 /***********************************************/
25 // ObjectArrayTest.h
26 class ObjectArrayTest
27 {
28     static
29     {
30         System.loadLibrary("objectarraytest");
31     }
32     private static native int[][] InitInt2DArray(int size);
33     
34     public static void main(String[] args)
35     {
36         int[][] int2DArr = InitInt2DArray(5);
37         for(int i = 0; i < 5; i++)
38         {
39             for(int j = 0; j < 5; j++)
40             {
41                 System.out.println(int2DArr + "  ");
42             }
43             System.out.println();
44         }        
45     }
46 }
47 
48 /***********************************************/
49 // ObjectArrayTest.cpp
50 #include "ObjectArrayTest.h"
51 
52 JNIEXPORT jobjectArray JNICALL Java_ObjectArrayTest_InitInt2DArray
53   (JNIEnv *env, jclass cls, jint size)
54   {
55       jobjectArray result;
56       int i;
57       jclass intArrCls = env->FindClass("[I");         /* "[I" 代表int[] */
58       if(intArrCls == NULL)
59       {
60           return NULL;
61       }
62       result = env->NewObjectArray(size, intArrCls, NULL);  /* result是一个对象数组,其中的元素类型为int[] */
63       if(result == NULL)
64       {
65           return NULL;
66       }
67       
68       for(i = 0; i < size; i++)
69       {
70           jint temp[256];
71           int j;
72           jintArray intArr = env->NewIntArray(size);     /* 创建size个int元素的一维数组 */
73           if(intArr = NULL)
74           {
75               return NULL;
76           }
77           for(j = 0; j < size; j++)
78           {
79               temp[j] = i + j;
80           }
81           env->SetIntArrayRegion(intArr, 0, size, temp);    /* 将temp中的内容复制到intArr中 */
82           env->SetObjectArrayElement(result, i, intArr);    /* 将intArr中的内容复制到result中以便返回 */
83           env->DeleteLocalRef(intArr);
84       }
85       return result;
86   }
原文地址:https://www.cnblogs.com/benxintuzi/p/4593437.html