想要查看jni函数的具体说明,可以查看百度文库的 jni此常用函数
1.部分类型转换及常用函数说明
1) 本地方法对Java字符串的操作
const jchar *GetStringChars(jstring str, jboolean*isCopy)
将一个jstring对象,转换为(UTF-16)编码的宽字符串(jchar*)。
const char *GetStringUTFChars(jstring str,jboolean *isCopy)
将一个jstring对象,转换为(UTF-8)编码的字符串(char*)
第一个参数传入一个指向Java 中String对象的jstring引用。第二个参数传入的是一个jboolean的指针,其值可以为NULL、JNI_TRUE、JNI_FLASE。
如果为JNI_TRUE则表示开辟内存,然后把Java中的String拷贝到这个内存中,然后返回指向这个内存地址的指针。
如果为JNI_FALSE,则直接返回指向Java中String的内存指针。这时不要改变这个内存中的内容,这将破坏String在Java中始终是常量的规则。
如果是NULL,则表示不关心是否拷贝字符串。
使用这两个函数取得的字符,在不使用的时候,要分别对应的使用下面两个函数来释放内存。
RealeaseStringChars(jstring jstr, const jchar*str)
RealeaseStringUTFChars(jstring jstr, constchar* str)
第一个参数指定一个jstring变量,即要释放的本地字符串的资源
第二个参数就是要释放的本地字符串
2) 创建Java String对象
jstring NewString(const jchar *unicode, jsizelen) // 根据传入的宽字符串创建一个Java String对象
jstring NewStringUTF(const char *utf) // 根据传入的UTF-8字符串创建一个Java String对象
3) 返回Java String对象的字符串长度
jsize GetStringLength(jstring jstr) //返回一个java String对象的字符串长度
jsize GetStringUTFLength(jstring jstr) //返回一个java String对象经过UTF-8编码后的字符串长度
使用示例:
JNIEXPORT jstring JNICALL Java_com_wonder_Utils_getString(JNIEnv *env,jclass arg, jstring prompt) {
const char* str = (*env)->GetStringUTFChars(env, prompt, 0);
jstring res = (*env)->NewStringUTF(env, str);
(*env)->ReleaseStringUTFChars(env, prompt, str);
return res;
}
4)Java数组在本地代码中的处理
我们可以使用GetFieldID获取一个Java数组变量的ID,然后用GetObjectFiled取得该数组变量到本地方法,返回值为jobject,然后我们可以强制转换为jArray类型。
typedef jarray jbooleanArray;
typedef jarray jbyteArray;
typedef jarray jcharArray;
typedef jarray jshortArray;
typedef jarray jintArray;
typedef jarray jlongArray;
typedef jarray jfloatArray;
typedef jarray jdoubleArray;
typedef jarray jobjectArray;
jArray类型是JNI定义的一个对象类型,它并不是C/C++的数组,如int[]数组,double[]数组等等。所以我们要把jArray类型转换为C/C++中的数组来操作。
JNIEnv定义了一系列的方法来把一个jArray类型转换为C/C++数组或把C/C++数组转换为jArray。
jsize GetArrayLength(jarray array) // 获得数组的长度
jobjectArray NewObjectArray(jsize len, jclass clazz, jobjectinit) // 创建对象数组,指定其大小
jobject GetObjectArrayElement(jobjectArray array, jsizeindex) // 获得数组的指定元素
void SetObjectArrayElement(jobjectArray array, jsizeindex,jobject val) // 设置数组元素
jbooleanArrayNewBooleanArray(jsize len) // 创建Boolean数组,指定其大小
jbyteArrayNewByteArray(jsize len) //下面的都类似,创建对应类型的数组,并指定大小
jcharArrayNewCharArray(jsize len)
jshortArrayNewShortArray(jsize len)
jintArrayNewIntArray(jsize len)
jlongArrayNewLongArray(jsize len)
jfloatArrayNewFloatArray(jsize len)
jdoubleArrayNewDoubleArray(jsize len)
// 获得指定类型数组的元素
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)
// 释放指定数组
void ReleaseBooleanArrayElements(jbooleanArrayarray,jboolean *elems,jint mode)
void ReleaseByteArrayElements(jbyteArray array,jbyte*elems,jint mode)
void ReleaseCharArrayElements(jcharArray array,jchar*elems,jint mode)
void ReleaseShortArrayElements(jshortArray array,jshort*elems,jint mode)
void ReleaseIntArrayElements(jintArray array,jint*elems,jint mode)
void ReleaseLongArrayElements(jlongArray array,jlong*elems,jint mode)
void ReleaseFloatArrayElements(jfloatArray array,jfloat*elems,jint mode)
void ReleaseDoubleArrayElements(jdoubleArrayarray,jdouble *elems,jint mode)
void * GetPrimitiveArrayCritical(jarray array, jboolean*isCopy)
void ReleasePrimitiveArrayCritical(jarray array, void*carray, jint mode)
void GetBooleanArrayRegion(jbooleanArray array,jsizestart, jsize len, jboolean *buf)
void GetByteArrayRegion(jbyteArray array,jsize start,jsize len, jbyte *buf)
void GetCharArrayRegion(jcharArray array,jsize start,jsize len, jchar *buf)
void GetShortArrayRegion(jshortArray array,jsize start,jsize len, jshort *buf)
void GetIntArrayRegion(jintArray array,jsize start,jsize len, jint *buf)
void GetLongArrayRegion(jlongArray array,jsize start,jsize len, jlong *buf)
void GetFloatArrayRegion(jfloatArray array,jsize start,jsize len, jfloat *buf)
void GetDoubleArrayRegion(jdoubleArray array,jsizestart, jsize len, jdouble *buf)
void SetBooleanArrayRegion(jbooleanArray array, jsizestart, jsize len,const jboolean *buf)
void SetByteArrayRegion(jbyteArray array, jsize start,jsize len,const jbyte *buf)
void SetCharArrayRegion(jcharArray array, jsize start,jsize len,const jchar *buf)
void SetShortArrayRegion(jshortArray array, jsizestart, jsize len,const jshort *buf)
void SetIntArrayRegion(jintArray array, jsize start,jsize len,const jint *buf)
void SetLongArrayRegion(jlongArray array, jsize start,jsize len,const jlong *buf)
void SetFloatArrayRegion(jfloatArray array, jsizestart, jsize len,const jfloat *buf)
void SetDoubleArrayRegion(jdoubleArray array, jsizestart, jsize len,const jdouble *buf)
上面是JNIEnv提供给本地代码调用的数组操作函数,大致可以分为下面几类:
1) 获取数组的长度
jsize GetArrayLength(jarray array);
2) 对象类型数组的操作
jobjectArray NewObjectArray(jsize len, jclassclazz,jobject init) // 创建
jobject GetObjectArrayElement(jobjectArray array, jsizeindex) // 获得元素
void SetObjectArrayElement(jobjectArray array, jsizeindex,jobject val) // 设置元素
JNI没有提供直接把Java的对象类型数组(Object[ ])直接转到C++中的jobject[ ]数组的函数。而是直接通过Get/SetObjectArrayElement这样的函数来对Java的Object[ ]数组进行操作
3) 对基本数据类型数组的操作
基本数据类型数组的操作方法比较多,大致可以分为如下几类:
GetArrayElements/RealeaseArrayElements;
GetArrayElements(Array arr, jboolean*isCopied);
这类函数可以把Java基本类型的数组转换到C/C++中的数组。有两种处理方式,一是拷贝一份传回本地代码,另一种是把指向Java数组的指针直接传回到本地代码,处理完本地化的数组后,通过RealeaseArrayElements来释放数组。处理方式由Get方法的第二个参数isCopied来决定。
RealeaseArrayElements(Arrayarr,* array, jint mode)用这个函数可以选择将如何处理Java和C/C++本地数组:
其第三个参数mode可以取下面的值:
l 0:对Java的数组进行更新并释放C/C++的数组
l JNI_COMMIT:对Java的数组进行更新但是不释放C/C++的数组
l JNI_ABORT:对Java的数组不进行更新,释放C/C++的数组
例如1:
Test.java
public class Test {
privateint [] arrays=new int[]{1,2,3,4,5};
publicnative void show();
static{
System.loadLibrary("NativeTest");
}
publicstatic void main(String[] args) {
newTest().show();
}
}
本地方法:
void native_test_show(JNIEnv * env, jobject obj)
{
jfieldIDid_arrsys=env->GetFieldID(env->GetObjectClass(obj),"arrays","[I");
jintArrayarr=(jintArray)(env->GetObjectField(obj, id_arrsys));
jint*int_arr=env->GetIntArrayElements(arr,NULL);
jsizelen=env->GetArrayLength(arr);
for(inti=0; i<len; i++)
{
cout<<int_arr[i]<<endl;
}
env->ReleaseIntArrayElements(arr,int_arr,JNI_ABORT);
}
例如2
JNIEXPORT jbyteArray JNICALL Java_com_wonder_Utils_getbyte(JNIEnv *env,
jclass arg, jbyteArray byteArr) {
int len = (*env)->GetArrayLength(env, byteArr);
jbyte* jarr = (*env)->GetByteArrayElements(env, byteArr, JNI_FALSE);
jbyteArray jarrRV = (*env)->NewByteArray(env, len);
(*env)->SetByteArrayRegion(env, jarrRV, 0, len, jarr);
return jarrRV;
}
JNIEXPORT jintArray JNICALL Java_com_wonder_Utils_getIntArray(JNIEnv *env,
jclass arg, jintArray intArr) {
jsize len = (*env)->GetArrayLength(env, intArr);
jint* carr = (*env)->GetIntArrayElements(env, intArr, JNI_FALSE);
int i;
for (i = 0; i < len; i++) {
*(carr + i) += 10;
}
return intArr;
}
5.对象和结构体的传递
示例:
typedef struct Info {
int id;
char name[100];
} Info_t;
package com.wonder;
public class Info {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return “Info [id=” + id + “, name=” + name + “]”;
}
}
C代码:
Java对象传递到c中
JNIEXPORT void JNICALL Java_com_wonder_Utils_sendObj(JNIEnv *env, jclass arg, jobject obj){
jclass cls_objClass = (*env)->GetObjectClass(env,obj);
jmethodID methodId = (*env)->GetMethodID(env,cls_objClass, “getName”,”()Ljava/lang/String;”);
jstring js_name = (jstring)(*env)->CallObjectMethod(env,obj,methodId,NULL);
}
将C中的结构体传递给Java对象
JNIEXPORT jint JNICALL Java_com_wonder_Utils_getInfo(JNIEnv *env, jclass arg,
jobject jobj) {
Info_t* bar = malloc(sizeof(Info_t));
jclass clazz;
jfieldID fid;
//init the bar data of C
strcpy(bar->name,”Info”);
bar->id = strlen(bar->name);
// mapping bar of C to foo
clazz = (*env)->GetObjectClass(env, jobj);
if(clazz==0){
return (-1);
}
fid = (*env)->GetFieldID(env, clazz, "id", "I");
(*env)->SetIntField(env,jobj,fid,bar->id);
fid = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
jstring name = (*env)->NewStringUTF(env, bar->name);
(*env)->SetObjectField(env,jobj,fid,name);
free(bar);
return 0;
}
使用方式
Info info = new Info();
info.setId(1);
info.setName(“aaa”);
Utils.sendObj(info);
Info info2 = new Info();
Utils.getInfo(info2);
详细的参考jni讲解
jni的数据结构解释参考jni数据结构解释
数据类型转化数据类型转化
jni函数解析jni函数大全
jni操作复杂对象