/********************************************************************************************
* author:conowen@大钟
* E-mail:conowen@hotmail.com
*http://blog.csdn.net/conowen
* 注:本文为原创,仅作为学习交流使用,转载请标明作者及出处。

********************************************************************************************/

在Java中有两类数据类型:primitive types,如,int, float, char;另一种为reference types,如,类,实例,数组。

注意:数组,不管是对象数组还是基本类型数组,都作为reference types存在,有专门的JNI方法取数组中每个元素。

1、void

java的void与JNI的void是一致的。

2、基本数据类型

3、对象类型

相比基本类型,对象类型的传递要复杂得多。不能对Jstring进行直接操作。

[java] view plain copy
  1. //如下使用方式是错误的,因为jstring不同于C语言中的char*类型。
  2. Java_com_conowen_test_testActivity_test(JNIEnv*env,jobjectobj,jstringstr)
  3. {
  4. /*ERROR:incorrectuseofjstringasachar*pointer*/
  5. printf("%s",str);
  6. ...
  7. }



注意:

[java] view plain copy
  1. typedefjintjsize;

3.1、GetStringUTFChars与ReleaseStringUTFChars函数简单说明(跳到3.2有更方便的函数)

JNI支持Unicode/UTF-8字符编码互转。Unicode以16-bits值编码;UTF-8是一种以字节为单位变长格式的字符编码,并与7-bitsASCII码兼容。UTF-8字串与C字串一样,以NULL('\0')做结束符, 当UTF-8包含非ASCII码字符时,以'\0'做结束符的规则不变。7-bit ASCII字符的取值范围在1-127之间,这些字符的值域与UTF-8中相同。当最高位被设置时,表示多字节编码。

[java] view plain copy
  1. //调用GetStringUTFChars,把一个Unicode字串转成UTF-8格式字串
  2. Java_com_conowen_test_testActivity_test(JNIEnv*env,jobjectobj,jstringstr)
  3. {
  4. charbuf[128];
  5. constjbyte*cbyte;
  6. cbyte=(*env)->GetStringUTFChars(env,str,NULL);
  7. if(cbyte==NULL){
  8. returnNULL;
  9. }
  10. printf("%s",cbyte);
  11. (*env)->ReleaseStringUTFChars(env,str,cbyte);
  12. scanf("%127s",buf);
  13. return(*env)->NewStringUTF(env,buf);
  14. //或者return(*env)->NewStringUTF(env,"helloworld");
  15. }

上述函数中,有isCopy参数,当该值为JNI_TRUE,将返回str的一个拷贝;为JNI_FALSE将直接指向str的内容。 注意:当isCopy为JNI_FALSE,不要修改返回值,不然将改变java.lang.String的不可变语义。一般会把isCopy设为NULL,不关心Java VM对返回的指针是否直接指向java.lang.String的内容。

注意:在调用GetStringChars之后,一定要调用ReleaseStringChars做释放,(Unicode -> UTF-8转换的原因)。不管在调用GetStringChars时为isCopy赋值JNI_TRUE还是JNI_FALSE,因不同JavaVM实现的原因,ReleaseStringChars可能释放内存,也可能释放一个内存占用标记。

3.2、GetStringRegion/GetStringUTFRegion函数简单说明

因为这两个函数不涉及内存操作,所以较GetStringUTFChars使用要简单。也不用进行释放指针之类的操作,非常方便。(推荐使用)

[java] view plain copy
  1. Java_com_conowen_test_testActivity_test(JNIEnv*env,jobjectobj,jstringstr)
  2. {
  3. charoutputbuf[128],inputbuf[128];
  4. intlen=(*env)->GetStringLength(env,str);
  5. (*env)->GetStringUTFRegion(env,str,0,len,outbuf);
  6. printf("%s",outputbuf);
  7. scanf("%s",inputbuf);
  8. return(*env)->NewStringUTF(env,inbuf);
  9. }

GetStringUTFRegion有两个主要的参数,start 和 length, 这两个参数以Unicode编码计算. 该函数会做边界检查,所以可能抛出StringIndexOutOfBoundsException。

3.3、GetStringLength/GetStringUTFLength函数简单说明

前者是Unicode编码长度,后者返回的是是UTF编码长度。

4、数组类型

JNI对每种数据类型的数组都有对应的函数。

4.1、常见错误操作:

[java] view plain copy
  1. /*直接操作数组是错误的*/
  2. Java_IntArray_sumArray(JNIEnv*env,jobjectobj,jintArrayarr)
  3. {
  4. inti,sum=0;
  5. for(i=0;i<10;i++){
  6. sum+=arr[i];
  7. }
  8. }

4.2、使用

void Get<Type>ArrayRegion(JNIEnv *env,<ArrayType> array, jsize start,jsize len, <NativeType> *buf);

进行操作

参数说明:

env:the JNIEnv interface pointer.

array:a reference to an array whose elements are to be copied.将要被拷贝的目标数组<ArrayType>

start:the starting index of the array elements to be copied.(数组的起始位置)

len:the number of elements to be copied.(拷贝元素的个数)buf:the destination buffer.存放结果的本地数组<NativeType>

返回值:void

[java] view plain copy
  1. Java_IntArray_sumArray(JNIEnv*env,jobjectobj,jintArrayarr)
  2. {
  3. jintbuf[10];
  4. jinti,sum=0;
  5. (*env)->GetIntArrayRegion(env,arr,0,10,buf);
  6. for(i=0;i<10;i++){
  7. sum+=buf[i];
  8. }
  9. returnsum;
  10. }
  11. JNI中数组的基类为jarray,其他如jintArray都是继承自jarray。

4.3、使用<NativeType> *Get<Type>ArrayElements(JNIEnv *env,<ArrayType> array, jboolean *isCopy);进行数组操作

参数说明:

env:the JNIEnv interface pointer.array: a reference to the primitive array whose elements are tobe accessed.(目标数组)

isCopy:a pointer to a jboolean indicating whether a function

返回值:返回指向Java数组的一个直接的指针

[java] view plain copy
  1. 使用实例:
  2. Java_IntArray_sumArray(JNIEnv*env,jobjectobj,jintArrayarr)
  3. {
  4. jint*carr;
  5. jinti,sum=0;
  6. carr=(*env)->GetIntArrayElements(env,arr,NULL);
  7. if(carr==NULL){
  8. return0;/*exceptionoccurred*/
  9. }
  10. for(i=0;i<10;i++){
  11. sum+=carr[i];
  12. }
  13. (*env)->ReleaseIntArrayElements(env,arr,carr,0);
  14. returnsum;
  15. }

更多数组操作函数:

5、另外一些有用的宏定义(来自jni.h)



[java] view plain copy
  1. #defineJNI_FALSE0
  2. #defineJNI_TRUE1
  3. #defineJNI_VERSION_1_10x00010001
  4. #defineJNI_VERSION_1_20x00010002
  5. #defineJNI_VERSION_1_40x00010004
  6. #defineJNI_VERSION_1_60x00010006
  7. #defineJNI_OK(0)/*noerror*/
  8. #defineJNI_ERR(-1)/*genericerror*/
  9. #defineJNI_EDETACHED(-2)/*threaddetachedfromtheVM*/
  10. #defineJNI_EVERSION(-3)/*JNIversionerror*/
  11. #defineJNI_COMMIT1/*copycontent,donotfreebuffer*/
  12. #defineJNI_ABORT2/*freebufferw/ocopyingback*/

更多相关文章

  1. android的ListView显示
  2. 真正的Android
  3. Android资源文件 - 使用资源存储字符串 颜色 尺寸 整型 布尔值
  4. Android电源管理
  5. android 开发-数据存储之文件存储
  6. Android日志系统Logcat源代码简要分析
  7. 谷歌推出新操作系统Andromeda,那Android真的将死吗
  8. Xposed框架之函数Hook学习
  9. android开发笔记:了解Android

随机推荐

  1. [Android记录]Eclipse关联android源码
  2. Gradle导入so文件
  3. android 8.1 去掉设置中搜索项或去掉其点
  4. 图片拖动功能实现
  5. 那些年收藏的技术文章(二)-云笔记篇
  6. Android之简易音乐播发器
  7. android的系统属性设置和应用
  8. Android版本更新提示框
  9. 升级Android Studio 3.2.1后 遇到问题
  10. 通过Android上的意图启动Google地图路线