zoukankan      html  css  js  c++  java
  • Android的NDK开发(3)————JNI数据类型的详解

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


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



    1、void

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


    2、基本数据类型





    3、对象类型



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

    1. //如下使用方式是错误的,因为jstring不同于C语言中的char *类型。  
    2. Java_com_conowen_test_testActivity_test(JNIEnv *env, jobject obj, jstring str)  
    3. {  
    4. /* ERROR: incorrect use of jstring as a char* pointer */  
    5. printf("%s", str);  
    6. ...  
    7. }  




    注意:

    1. typedef jint jsize;  





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

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


    1. //调用GetStringUTFChars,把一个Unicode字串转成UTF-8格式字串  
    2.   
    3. Java_com_conowen_test_testActivity_test(JNIEnv *env, jobject obj, jstring str)  
    4. {  
    5. char buf[128];  
    6. const jbyte *cbyte;  
    7. cbyte= (*env)->GetStringUTFChars(env, str, NULL);  
    8. if (cbyte== NULL) {  
    9. return NULL;  
    10. }  
    11. printf("%s", cbyte);  
    12. (*env)->ReleaseStringUTFChars(env, str, cbyte);  
    13.   
    14. scanf("%127s", buf);  
    15. return (*env)->NewStringUTF(env, buf);  
    16.   
    17. //或者return (*env)->NewStringUTF(env, "hello world");  
    18.  }  

             上述函数中,有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使用要简单。也不用进行释放指针之类的操作,非常方便。(推荐使用)


    1. Java_com_conowen_test_testActivity_test(JNIEnv *env, jobject obj, jstring str)  
    2. {  
    3.   
    4. char outputbuf[128], inputbuf[128];  
    5. int len = (*env)->GetStringLength(env, str);  
    6. (*env)->GetStringUTFRegion(env, str, 0, len, outbuf);  
    7. printf("%s", outputbuf);  
    8. scanf("%s", inputbuf);  
    9. return (*env)->NewStringUTF(env, inbuf);  
    10. }  


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


    3.3、GetStringLength/GetStringUTFLength函数简单说明


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


    4、数组类型





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

    1. /* 直接操作数组是错误的 */  
    2. Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)  
    3. {  
    4. int i, 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



    1. Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)  
    2. {  
    3. jint buf[10];  
    4. jint i, sum = 0;  
    5. (*env)->GetIntArrayRegion(env, arr, 0, 10, buf);  
    6. for (i = 0; i < 10; i++) {  
    7. sum += buf[i];  
    8. }  
    9. return sum;  
    10. }  
    11.   
    12. 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数组的一个直接的指针


    1. 使用实例:  
    2.   
    3. Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)  
    4. {  
    5. jint *carr;  
    6. jint i, sum = 0;  
    7. carr = (*env)->GetIntArrayElements(env, arr, NULL);  
    8. if (carr == NULL) {  
    9. return 0; /* exception occurred */  
    10. }  
    11. for (i=0; i<10; i++) {  
    12. sum += carr[i];  
    13. }  
    14. (*env)->ReleaseIntArrayElements(env, arr, carr, 0);  
    15. return sum;  
    16. }  
    17.   
    18.   
    19. )  


    更多数组操作函数:

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



      1. #define JNI_FALSE   0  
      2. #define JNI_TRUE    1  
      3.   
      4. #define JNI_VERSION_1_1 0x00010001  
      5. #define JNI_VERSION_1_2 0x00010002  
      6. #define JNI_VERSION_1_4 0x00010004  
      7. #define JNI_VERSION_1_6 0x00010006  
      8.   
      9. #define JNI_OK          (0)         /* no error */  
      10. #define JNI_ERR         (-1)        /* generic error */  
      11. #define JNI_EDETACHED   (-2)        /* thread detached from the VM */  
      12. #define JNI_EVERSION    (-3)        /* JNI version error */  
      13.   
      14. #define JNI_COMMIT      1           /* copy content, do not free buffer */  
      15. #define JNI_ABORT       2           /* free buffer w/o copying back */ 
  • 相关阅读:
    SGU 495 Kids and Prizes 概率DP 或 数学推理
    poj 2799 IP Networks 模拟 位运算
    uva 202 Repeating Decimals 模拟
    poj 3158 Kickdown 字符串匹配?
    uva 1595 Symmetry 暴力
    uva 201 Squares 暴力
    uva 1594 Ducci Sequence 哈希
    uva 1368 DNA Consensus String 字符串
    数字、字符串、列表的常用操作
    if条件判断 流程控制
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/6154887.html
Copyright © 2011-2022 走看看