您的位置:首页 > 编程语言 > C语言/C++

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

2015-06-22 16:21 666 查看
关于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型数组的和:

 // IntArray.java
class IntArray
{
static
{
System.loadLibrary("intarray");
}
private native int SumArray(int[] arr);

public static void main(String[] args)
{
IntArray p = new IntArray();
int arr[] = new int[10];
for(int i = 0; i < 10; i++)
{
arr[i] = i;
}
int sum = p.SumArray(arr);
System.out.println("sum = " + sum);
}
}

/***********************************************/
 // Intarray.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class IntArray */

#ifndef _Included_IntArray
#define _Included_IntArray
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     IntArray
* Method:    SumArray
* Signature: ([I)I
*/
JNIEXPORT jint JNICALL Java_IntArray_SumArray
(JNIEnv *, jobject, jintArray);

#ifdef __cplusplus
}
#endif
#endif

/***********************************************/
 // IntArray.c
#include "IntArray.h"

JNIEXPORT jint JNICALL Java_IntArray_SumArray
(JNIEnv *env, jobject obj, jintArray arr)
{
jint buf[10];
jint i, sum = 0;
(*env)->GetIntArrayRegion(env, arr, 0, 10, buf);
for(i = 0; i < 10; i++)
{
sum += buf[i];
}
return sum;
}


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

 //ObjectArrayTest.java
class ObjectArrayTest
{
static
{
System.loadLibrary("objectarraytest");
}
private static native int[][] InitInt2DArray(int size);

public static void main(String[] args)
{
int[][] int2DArr = InitInt2DArray(5);
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < 5; j++)
{
System.out.println(int2DArr + "  ");
}
System.out.println();
}
}
}

/***********************************************/
 // ObjectArrayTest.h
class ObjectArrayTest
{
static
{
System.loadLibrary("objectarraytest");
}
private static native int[][] InitInt2DArray(int size);

public static void main(String[] args)
{
int[][] int2DArr = InitInt2DArray(5);
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < 5; j++)
{
System.out.println(int2DArr + "  ");
}
System.out.println();
}
}
}

/***********************************************/
 // ObjectArrayTest.cpp
#include "ObjectArrayTest.h"

JNIEXPORT jobjectArray JNICALL Java_ObjectArrayTest_InitInt2DArray
(JNIEnv *env, jclass cls, jint size)
{
jobjectArray result;
int i;
jclass intArrCls = env->FindClass("[I");         /* "[I" 代表int[] */
if(intArrCls == NULL)
{
return NULL;
}
result = env->NewObjectArray(size, intArrCls, NULL);  /* result是一个对象数组,其中的元素类型为int[] */
if(result == NULL)
{
return NULL;
}

for(i = 0; i < size; i++)
{
jint temp[256];
int j;
jintArray intArr = env->NewIntArray(size);     /* 创建size个int元素的一维数组 */
if(intArr = NULL)
{
return NULL;
}
for(j = 0; j < size; j++)
{
temp[j] = i + j;
}
env->SetIntArrayRegion(intArr, 0, size, temp);    /* 将temp中的内容复制到intArr中 */
env->SetObjectArrayElement(result, i, intArr);    /* 将intArr中的内容复制到result中以便返回 */
env->DeleteLocalRef(intArr);
}
return result;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: