/********************************************************************************************
* 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操作SQLite数据库基本模式
  2. Android(安卓)APP Package操作类
  3. android操作sdcard
  4. Android(安卓)GPS基础
  5. Android(安卓)Studio代码笔记09.自定义视图
  6. Android的NDK开发(3)————JNI数据类型的详解
  7. android两种方法操作Sqlite数据库
  8. Android计算器
  9. android的ListView显示

随机推荐

  1. android property
  2. jWebSocket for Android
  3. Android PopupWindow显示位置和显示大小
  4. Android 工具类
  5. Android 全屏显示实例
  6. android 文件系统分析
  7. android的一个编译问题
  8. Android CTS Debug
  9. Android training
  10. android:allowBackup="true"