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_75\include –I D:\jdk1.7.0_75\include\win32 IntArray.c –o intarray.dll

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

g++ -Wl,--kill-at –shared –I D:\jdk1.7.0_75\include –I D:\jdk1.7.0_75\include\win32 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   }

 

你可能感兴趣的:(java)