JNI常用数据类型转换库函数使用总结

来源:互联网 发布:qq秀照片秀网络繁忙 编辑:程序博客网 时间:2024/05/21 09:18

JNI有很多库函数,这会让人头晕眼花,通过实践摸索出来的用法总结如下:
0、jclass FindClass(const char *name) ;
获取java的类,是获取一种类的定义,在New**Array的时候用到。
例如:
jclass obj = env->FindClass(“/struct”);
1、jclass jann = env->GetObjectClass(ann);获取java传进来的ann类信息,在JNI中更名为jann,这一步是JNI中想要访问java传进来的class类的第一步,在GetFieldID()中使用。
2、 jfieldID GetFieldID(jclass clazz, const char *name, const char *sig);
例如:
jfieldID aId = env->GetFieldID(jann, “a”, “I”);
获取ann类中成员的定义,将java类中的成员提取出来,用jfieldID来标识成员。
其中GetFieldID()参数中的“a”就是ann类成员a,“I”为类成员对应的类型(int型),主要类型的相应签名表示如下:
Z ———————boolean
B ———————byte
C ——————– char
S———————short
I——————— int
J———————-long
F———————-float
D———————double
[ type—————–type[]
[[type—————–type[][]

3、jint GetIntField(jobject obj, jfieldID fieldID);
例如:
jint _a = env->GetIntField(ann, aId);
将jann类中的aId对应的Int型成员(a)内容取到jint _a中,注意这里用的是jobject类型的ann,不是jcalss类型的jann。
根据不同的数据类型,相应的取基础类型内容的函数有:
jshort GetShortField(jobject obj, jfieldID fieldID);
jlong GetLongField(jobject obj, jfieldID fieldID);
jfloat GetFloatField(jobject obj, jfieldID fieldID);
jdouble GetDoubleField(jobject obj, jfieldID fieldID);

4、jobject GetObjectField(jobject obj, jfieldID fieldID)
3讲的是基础类型,4是一维、二维数组类型。
5、 jobject GetObjectArrayElement(jobjectArray array, jsize index) ;
获取object数组元素,这个一般用在二维数组上,将一维数组视为object,那二维数组就是object的序列,即objectArray。该函数可以获取二维数组的一行,即一维数组。index指定获取object序列中的第几个元素,即二维数组中的第几行。
由于该函数的返回值是jobject,当具体到类型时,需要强制类型转换,例如:
jint b = (jint )env->GetObjectArrayElement(jann, i);
i为元素的索引。
6、 jint * (JNICALL *GetIntArrayElements);
获取数组中的元素,可以将IntArray中的元素获取,转存到jint 类型的数组中,之所以要转换成jint 类型,是因为jint 可以遍历每个元素直接给C数据类型int 赋值,这样就可以完成java数据类型与C数据类型之间的转换。
相似的有:
jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy);
jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy);
jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy);
jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) ;
jint * GetIntArrayElements(jintArray array, jboolean *isCopy) ;
jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy);
jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy);
jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy);

7、 jsize GetArrayLength(jarray array) ;
获取array的长度,如果是一维数组,那么获取到一维数组的长度,如果是二维数组,获取到的是二维数组的行数。可以用int来存储返回值。

1~7为从java获取数值,下面是JNI将值返回给java
8、 void SetIntField(jobject obj, jfieldID fieldID, jint val);
将基础类型返回java比较简单,直接调用该函数,输入相应的参数即可将C的数值返回给java。
例如:
int atest = 10;
env->SetShortField(ann, aFieldId, atest);
第三个参数(jint val)可以直接用相应的C基础类型。
void SetBooleanField(jobject obj, jfieldID fieldID,jboolean val);
void SetByteField(jobject obj, jfieldID fieldID,jbyte val);
void SetCharField(jobject obj, jfieldID fieldID,jchar val);
void SetShortField(jobject obj, jfieldID fieldID, jshort val);
void SetLongField(jobject obj, jfieldID fieldID,jlong val);
void SetFloatField(jobject obj, jfieldID fieldID,jfloat val);
void SetDoubleField(jobject obj, jfieldID fieldID,jdouble val);

9、 jintArray NewIntArray(jsize len);
新建jarray。
相似的有:
jbooleanArray NewBooleanArray(jsize len);
jbyteArray NewByteArray(jsize len);
jcharArray NewCharArray(jsize len) ;
jshortArray NewShortArray(jsize len) ;
jintArray NewIntArray(jsize len) ;
jlongArray NewLongArray(jsize len) ;
jfloatArray NewFloatArray(jsize len);
jdoubleArray NewDoubleArray(jsize len);
jobjectArray NewObjectArray(jsize len, jclass clazz,jobject init);

10、 void SetIntArrayRegion(jintArray array, jsize start, jsize len,const jint *buf);
用JNI数组类型给jarray类型赋值。
例如:
jint tmp[2] = {1,2};
jintArray test = env->NewIntArray(2);
env->SetIntArrayRegion(test, 0, 2, tmp);

相似的还有其他基础数据类型的库函数,改变类型名即可,不列举了。
之所以要将jint[]的值赋给jintArray,是因为给object数组赋值(进而将二维数组返回给java),需要用jarray来进行,参见11.

11、void SetObjectArrayElement(jobjectArray array, jsize index, jobject val);
上接9,env->SetObjectArrayElement(Obj, i, test);
如此就完成了JNI中jobjectArray的构建,从而通过jobjectArray将数值返回给java。

12、void SetObjectField(jobject obj, jfieldID fieldID, jobject val);
将jobjectArray 返回给java。
例如:
jobjectArray = env->NewObjectArray(len, objClass, 0);
env->SetObjectField(ann, objFieldId, Obj);

以ann的一维数组int[] b为例:
//一、先从b获取数据。
jfieldID bId = env->GetFieldID(jann, “b”, “[I”);
jintArray j_b = (jintArray)env->GetObjectField(ann, bId);
int len = env->GetArrayLength(j_b);
jint *jintb= NULL;
if (j_b > 0)
{
int *c_b ;
jintb = env->GetIntArrayElements(j_b, NULL);
for (int j = 0; j < len; j++)
{
c_b = jintb[j];
//将java数组数据获取到了C的数组c_b中。
}
}
env->ReleaseIntArrayElements(j_b, jintb, 0);
//释放空间,否则多了会内存泄漏。

//二、将C数据返回给b

int c[2] = {1,2};
jintArray tmp = env->NewIntArray(2);
jint jtmp[2];
for (int j = 0; i < 2; j++)
{
jtmp[j] = c[j];
}
env->SetIntArrayRegion(tmp,0,2,jtmp);
env->SetObjectField(ann, bId, tmp);
/env->ReleaseIntArrayElements(tmp, jtmp, 0); 此时不应该使用该释放空间的语句,如果释放了,java就获取不到该内存空间里面的内容了。/

附转转自网络的JNI数据类型对应表:
http://blog.csdn.net/moon_nife/article/details/51611557

根据相应的类型,调用相对应的JNI库函数

根据相应的类型,调用相对应的JNI库函数。关于JNI在java和C之间的桥接关系,请参阅我的另外一篇博客:
http://blog.csdn.net/seuzhouchenglong/article/details/78053868