jni 接口说明
1 JNI中GetStringChars
- JNI中GetStringChars函数中的isCopy
- 定义:
const char * GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy)
isCopy
:当函数执行完后,isCopy ==JNI_TRUE
表示得到的字符串是 java.lang.String 的拷贝;isCopy ==JNI_FALSE
表示得到的字符串是 java.lang.String 引用,本地代码决不能修改字符串的内容,否则JVM中的原始字符串也会被修改,这会打破JAVA语言中字符串不可变的规则。
- 注意:
- 通常我们不关注 isCopy 的值,可以传NULL。
- 在不再使用返回的字符串,需要调用
ReleaseStringUTFChars
进行释放。
- 示例
JNIEXPORT jstring JNICALL Java_com_study_jnilearn_Sample_sayHello(JNIEnv *env, jclass cls, jstring j_str)
{
const char *c_str = NULL;
char buff[128] = {0};
jboolean isCopy; // 返回JNI_TRUE表示原字符串的拷贝,返回JNI_FALSE表示返回原字符串的指针
c_str = (*env)->GetStringUTFChars(env, j_str, &isCopy);
printf("isCopy:%d\n", isCopy);
if (c_str == NULL)
{
return NULL;
}
printf("C_str: %s \n", c_str);
sprintf(buff, "hello %s", c_str);
(*env)->ReleaseStringUTFChars(env, j_str, c_str);
return (*env)->NewStringUTF(env, buff);
}
2 获取实例变量
- 涉及接口:
jclass GetObjectClass(JNIEnv *env, jobject obj);
:从对象获取类名
jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
:从对象中获取属性字段的id
_NativeType_ _Get<type>Field_(JNIEnv *env, jobject obj, jfieldIfieldID)
:根据对象和属性 id 获取相应的属性值
- 不同类型获取值函数如下
|
Get<type>Field Routine Name
| Native Type |
| --------------------------- | ----------- |
| GetObjectField()
| jobject |
| GetBooleanField()
| jboolean |
| GetByteField()
| jbyte |
| GetCharField()
| jchar |
| GetShortField()
| jshort |
| GetIntField()
| jint |
| GetLongField()
| jlong |
| GetFloatField()
| jfloat |
| GetDoubleField()
| jdouble |
- 示例
JNIEXPORT void JNICALL Java_com_study_jnilearn_AccessField_accessInstanceField(JNIEnv *env, jclass cls, jobject obj)
{
jclass clazz;
jfieldID fid;
jstring j_str;
jstring j_newStr;
const char *c_str = NULL;
// 1.获取AccessField类的Class引用
clazz = (*env)->GetObjectClass(env, obj);
if (clazz == NULL)
{
return;
}
// 2. 获取AccessField类实例变量str的属性ID
fid = (*env)->GetFieldID(env, clazz, "str", "Ljava/lang/String;");
if (clazz == NULL)
{
return;
}
// 3. 获取实例变量str的值
j_str = (jstring)(*env)->GetObjectField(env, obj, fid);
// 4. 将unicode编码的java字符串转换成C风格字符串
c_str = (*env)->GetStringUTFChars(env, j_str, NULL);
if (c_str == NULL)
{
return;
}
printf("In C--->ClassField.str = %s\n", c_str);
(*env)->ReleaseStringUTFChars(env, j_str, c_str);
// 5. 修改实例变量str的值
j_newStr = (*env)->NewStringUTF(env, "This is C String");
if (j_newStr == NULL)
{
return;
}
(*env)->SetObjectField(env, obj, fid, j_newStr);
// 6.删除局部引用
(*env)->DeleteLocalRef(env, clazz);
(*env)->DeleteLocalRef(env, j_str);
(*env)->DeleteLocalRef(env, j_newStr);
}
3 获取静态变量
- 涉及接口:
jclass FindClass(JNIEnv *env, const char *name);
:通过类签名找到类
jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
:通过类、字段属性名、字段类型签名找到字段id
_NativeType_ _GetStatic<type>Field_ (JNIEnv *env, jclass clazz, jfieldID fieldID);
:根据类和字段 id 获取相应的字段值
- 不同类型获取静态值函数如下
GetStatic<type>Field Routine Name |
Native Type |
GetStaticObjectField() |
jobject |
GetStaticBooleanField() |
jboolean |
GetStaticByteField() |
jbyte |
GetStaticCharField() |
jchar |
GetStaticShortField() |
jshort |
GetStaticIntField() |
jint |
GetStaticLongField() |
jlong |
GetStaticFloatField() |
jfloat |
GetStaticDoubleField() |
jdouble |
JNIEXPORT void JNICALL Java_com_study_jnilearn_AccessField_accessStaticField(JNIEnv *env, jclass cls)
{
jclass clazz;
jfieldID fid;
jint num;
// 1.获取ClassField类的Class引用
clazz = (*env)->FindClass(env, "com/study/jnilearn/ClassField");
if (clazz == NULL)
{ // 错误处理
return;
}
// 2.获取ClassField类静态变量num的属性ID
fid = (*env)->GetStaticFieldID(env, clazz, "num", "I");
if (fid == NULL)
{
return;
}
// 3.获取静态变量num的值
num = (*env)->GetStaticIntField(env, clazz, fid);
printf("In C--->ClassField.num = %d\n", num);
// 4.修改静态变量num的值
(*env)->SetStaticIntField(env, clazz, fid, 80);
// 删除属部引用
(*env)->DeleteLocalRef(env, clazz);
}
4 数组
4.1 获取数组长度
jsize GetArrayLength(JNIEnv *env, jarray array);
: 返回数组长度
4.2 基本类型数组
4.2.1 获取基本类型数组
- 获取数组的元素有 2 种方法:
NativeType *Get<PrimitiveType>ArrayElements(JNIEnv *env, ArrayType array, jboolean *isCopy);
:返回数组首地址
env
: the JNI interface pointer.
array
: a Java string object.
isCopy
: a pointer to a boolean.
void Get<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array, jsize start, jsize len, NativeType *buf);
:获取基本类型数组区间
env
: the JNI interface pointer.
array
: a Java array.
start
: the starting index.
len
: the number of elements to be copied.
buf
: the destination buffer.
Get<PrimitiveType>ArrayElements
函数簇如下:
Get<PrimitiveType>ArrayElements Routines |
Array Type |
Native Type |
GetBooleanArrayElements() |
jbooleanArray |
jboolean |
GetByteArrayElements() |
jbyteArray |
jbyte |
GetCharArrayElements() |
jcharArray |
jchar |
GetShortArrayElements() |
jshortArray |
jshort |
GetIntArrayElements() |
jintArray |
jint |
GetLongArrayElements() |
jlongArray |
jlong |
GetFloatArrayElements() |
jfloatArray |
jfloat |
GetDoubleArrayElements() |
jdoubleArray |
jdouble |
Get<PrimitiveType>ArrayRegion
函数簇如下:
Get<PrimitiveType>ArrayRegion Routine |
Array Type |
Native Type |
GetBooleanArrayRegion() |
jbooleanArray |
jboolean |
GetByteArrayRegion() |
jbyteArray |
jbyte |
GetCharArrayRegion() |
jcharArray |
jchar |
GetShortArrayRegion() |
jshortArray |
jhort |
GetIntArrayRegion() |
jintArray |
jint |
GetLongArrayRegion() |
jlongArray |
jlong |
GetFloatArrayRegion() |
jfloatArray |
jloat |
GetDoubleArrayRegion() |
jdoubleArray |
jdouble |
4.2.2 释放基本类型数组
void Release<PrimitiveType>ArrayElements (JNIEnv *env, ArrayType array, NativeType *elems, jint mode);
:释放数组
env
: the JNI interface pointer.
array
: a Java array object.
elems
: a pointer to array elements.
mode
: the release mode.
Release<PrimitiveType>ArrayElements
函数簇如下:
Release<PrimitiveType>ArrayElements Routines |
Array Type |
Native Type |
ReleaseBooleanArrayElements() |
jbooleanArray |
jboolean |
ReleaseByteArrayElements() |
jbyteArray |
jbyte |
ReleaseCharArrayElements() |
jcharArray |
jchar |
ReleaseShortArrayElements() |
jshortArray |
jshort |
ReleaseIntArrayElements() |
jintArray |
jint |
ReleaseLongArrayElements() |
jlongArray |
jlong |
ReleaseFloatArrayElements() |
jfloatArray |
jfloat |
ReleaseDoubleArrayElements() |
jdoubleArray |
jdouble |
4.2.3 设置基本类型数组元素值
主要有 2 种方法:
1. 直接使用 void Set<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array, jsize start, jsize len, const NativeType *buf);
函数簇
1. env
: the JNI interface pointer.
2. array
: a Java array.
3. start
: the starting index.
4. len
: the number of elements to be copied.
5. buf
: the source buffer.
2. 先使用 Get<PrimitiveType>ArrayElements
得到数组指针,再使用 Set<PrimitiveType>ArrayRegion
函数簇,最后使用 Release<PrimitiveType>ArrayElements
释放
void JNICALL Java_com_test_vediochat_h264_H264Android_test(JNIEnv *env, jobject thiz, jintArray javaArray, jbyteArray array2)
{
//方法一
/*
jint temp1 = 45,temp2 = 20;
(*env)->SetIntArrayRegion(env,javaArray,1,1,&temp1);
(*env)->SetIntArrayRegion(env,javaArray,2,1,&temp2);
*/
//方法二:
jint *tempSize = (jint *)(*env)->GetIntArrayElements(env, javaArray, 0);
tempSize[2] = 65;
tempSize[3] = 75;
(*env)->SetIntArrayRegion(env, javaArray, 0, 3, tempSize);
(*env)->ReleaseIntArrayElements(env, javaArray, tempSize, 0);
}
Set<PrimitiveType>ArrayRegion
函数簇如下
| Set<PrimitiveType>ArrayRegion Routine
| Array Type | Native Type |
| ------------------------------------- | ------------- | ----------- |
| SetBooleanArrayRegion()
| jbooleanArray | jboolean |
| SetByteArrayRegion()
| jbyteArray | jbyte |
| SetCharArrayRegion()
| jcharArray | jchar |
| SetShortArrayRegion()
| jshortArray | jshort |
| SetIntArrayRegion()
| jintArray | jint |
| SetLongArrayRegion()
| jlongArray | jlong |
| SetFloatArrayRegion()
| jfloatArray | jfloat |
| SetDoubleArrayRegion()
| jdoubleArray | jdouble |
4.3 对象数组
对象只能从数组中一个一个的访问,和基本类型返回数组首地址不同。
4.3.1 获取对象类型数组
jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index);
:获取指定索引的对象
4.3.2 设置对象类型数组元素值
void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value)
:设置指定索引的对象
env
: the JNI interface pointer.
array
: a Java array.
index
: array index.
value
: the new value.