JNI编程之如何传递参数(二)——数组类型的传递

Python09

JNI编程之如何传递参数(二)——数组类型的传递,第1张

来看一个传递int数组的例子,Java程序就不写了,JNIEXPORT jintJNICALL Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr) { jint *carrcarr = env->GetIntArrayElements(arr, false)if(carr == NULL) { return 0/* exception occurred */ } jint sum = 0for(int i=0i<10i++) { sum += carr[i]} env->ReleaseIntArrayElements(arr, carr, 0)return sum}这个例子中的GetIntArrayElements和ReleaseIntArrayElements函数就是JNI提供用于处理int数组的函 数。如果试图用arr[i]的方式去访问jintArray类型,毫无疑问会出错。JNI还提供了另一对函数GetIntArrayRegion和 ReleaseIntArrayRegion访问int数组,就不介绍了,对于其他基本类型的数组,方法类似。二维数组和String数组在JNI中,二维数组和String数组都被视为object数组,因为数组和String被视为object。仍然用一个例子来说明,这次是一个二维int数组,作为返回值。JNIEXPORTjobjectArray JNICALL Java_ObjectArrayTest_initInt2DArray(JNIEnv *env, jclasscls, int size) { jobjectArray resultjclass intArrCls = env->FindClass("[I")result = env->NewObjectArray(size, intArrCls, NULL)for (int i = 0i <sizei++) { jint tmp[256]/* make sure it is large enough! */ jintArray iarr = env->NewIntArray(size)for(int j = 0j <sizej++) { tmp[j] = i + j} env->SetIntArrayRegion(iarr, 0, size, tmp)env->SetObjectArrayElement(result, i, iarr)env->DeleteLocalRef(iarr)} return result}上面代码中的第三行,jobjectArray result因为要返回值,所以需要新建一个jobjectArray对象。jclass intArrCls = env->FindClass("[I")是创建一个jclass的引用,因为result的元素是一维int数组的引用,所以intArrCls必须是一维int数组的引用,这一点是如何保证的 呢?注意FindClass的参数"[I",JNI就是通过它来确定引用的类型的,I表示是int类型,[标识是数组。对于其他的类型,都有相应的表示方 法,Z booleanB byteC charS shortI intJ longF floatD doubleString是通过“Ljava/lang/String”表示的,那相应的,String数组就应该是“[Ljava/lang/String”。还是回到代码,result = env->NewObjectArray(size, intArrCls, NULL)的作用是为result分配空间。

java数组传递给jni实际是指针,只是java禁止你直接在jni里对java数组操作,所以在jni需要对java数组转换为jni里可以操作的数组。典型的还有字符串,c struct等。

之所以禁止jni直接操作数组可能是jvm在安全等方面的考虑。jni调用涉及到java内存栈和native内存栈。jvm只能处理到java内存,没有实现自动管理jni调用的内存。试想下如果jni里操作java数组刚好被回收了会怎样?

所以在jni里需要拷贝java数组副本,而且分配或者是引用了对象,需要手动释放删除(DeleteLocalRef、ReleaseXX)。jni调用实际是个很大的开销.

1、在c语言里(默认JNI传参)

jstring jstr

char words[]="中文\n"

jstr=(*env)->NewStringUTF(env,words)

return jstr

java的方法返回类型是String

这样就能在c语言的方法里一个字符串然后传回给java

2、JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少要保证本地代码能工作在任何Java 虚拟机环境下。