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('\0')做结束符,
当UTF-8包含非ASCII码字符时,以'\0'做结束符的规则不变。7-bit
ASCII字符的取值范围在1-127之间,这些字符的值域与UTF-8中相同。当最高位被设置时,表示多字节编码。

  1. //调用GetStringUTFChars,把一个Unicode字串转成UTF-8格式字串
  2. Java_com_conowen_test_testActivity_test(JNIEnv *env, jobject obj, jstring str)
  3. {
  4. char buf[128];
  5. const jbyte *cbyte;
  6. cbyte= (*env)->GetStringUTFChars(env, str, NULL);
  7. if (cbyte== NULL) {
  8. return NULL;
  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, "hello world");
  15. }

上述函数中,有isCopy参数,当该值为JNI_TRUE,将返回str的一个拷贝;为JNI_FALSE将直接指向str的内容。
注意:当isCopy为JNI_FALSE,不要修改返回值,不然将改变java.lang.String的不可变语义。一般会把isCopy设为NULL,不关心JavaVM对返回的指针是否直接指向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. char outputbuf[128], inputbuf[128];
  4. int len = (*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对每种数据类型的数组都有对应的函数。

  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. 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. Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
  3. {
  4. jint *carr;
  5. jint i, sum = 0;
  6. carr = (*env)->GetIntArrayElements(env, arr, NULL);
  7. if (carr == NULL) {
  8. return 0; /* exception occurred */
  9. }
  10. for (i=0; i<10; i++) {
  11. sum += carr[i];
  12. }
  13. (*env)->ReleaseIntArrayElements(env, arr, carr, 0);
  14. return sum;
  15. }

更多数组操作函数:

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

    1. #define JNI_FALSE   0
    2. #define JNI_TRUE    1
    3. #define JNI_VERSION_1_1 0x00010001
    4. #define JNI_VERSION_1_2 0x00010002
    5. #define JNI_VERSION_1_4 0x00010004
    6. #define JNI_VERSION_1_6 0x00010006
    7. #define JNI_OK          (0)         /* no error */
    8. #define JNI_ERR         (-1)        /* generic error */
    9. #define JNI_EDETACHED   (-2)        /* thread detached from the VM */
    10. #define JNI_EVERSION    (-3)        /* JNI version error */
    11. #define JNI_COMMIT      1           /* copy content, do not free buffer */
    12. #define JNI_ABORT       2           /* free buffer w/o copying back */

Android的NDK开发(3)————JNI数据类型的详解的更多相关文章

  1. Android的NDK开发(4)————JNI数据结构之JNINativeMethod

    转至:http://blog.csdn.net/conowen/article/details/7524744 1.JNINativeMethod 结构体的官方定义 typedef struct { ...

  2. Android 音视频开发(六): MediaCodec API 详解

    在学习了Android 音视频的基本的相关知识,并整理了相关的API之后,我们应该对基本的音视频有一定的轮廓了. 下面开始接触一个Android音视频中相当重要的一个API: MediaCodec.通 ...

  3. Android之NDK开发(转)

    Android之NDK开发 一.NDK产生的背景 Android平台从诞生起,就已经支持C.C++开发.众所周知,Android的SDK基于Java实现,这意味着基于Android SDK进行开发的第 ...

  4. Android之NDK开发

    转自:http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支持C ...

  5. 【转】Android之NDK开发

    原文网址:http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支 ...

  6. Android之NDK开发(转载)

    http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支持C.C+ ...

  7. Delphi使用android的NDK是通过JNI接口,封装好了,不用自己写本地代码,直接调用

    一.Android平台编程方式:      1.基于Android SDK进行开发的第三方应用都必须使用Java语言(Android的SDK基于Java实现)      2.自从ndk r5发布以后, ...

  8. 【Android】Android Studio NDK 开发

    Android Studio NDK 开发 记录在Android Studio中NDK简单开发的步骤 用到的Android Studio版本为3.5. 配置NDK 下载NDK 一般在SDK下已经有自带 ...

  9. Android下NDK开发环境搭建

    Android下NDK开发环境搭建 1.     AndroidNDK安装与配置 1.1  NDK简介 Android NDK是一套允许开发人员使用本地代码(如C/C++)进行Android APP部 ...

随机推荐

  1. Codeforces 919F. A Game With Numbers(博弈论)

      Imagine that Alice is playing a card game with her friend Bob. They both have exactly 88 cards and ...

  2. Spider_reg

    # 解析 数据的分类 结构化数据 有固定的格式,如 :HTML.XML.JSON 非结构化数据 图片.音频.视频,这类数据一般都存储为二进制 # 正则表达式 re 使用流程 创建编译对象:p = re ...

  3. 【Educational Codeforces Round 35 D】Inversion Counting

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 排列中交换任意两个数字. 排列的逆序对个数的奇偶性会发生变化. 翻转这个过程其实就是len/2对数字发生交换. 交换了偶数次的话,不 ...

  4. 【Uva 11080】Place the Guards

    [Link]: [Description] 一些城市,之间有道路相连,现在要安放警卫,警卫能看守到当前点周围的边,一条边只能有一个警卫看守,问是否有方案,如果有最少放几个警卫. [Solution] ...

  5. HDU1203 I NEED A OFFER! 【贪心】

    I NEED A OFFER! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. Android时间戳与字符串相互转换

    import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public cl ...

  7. 日历控件input框默认显示当日日期

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script sr ...

  8. amazeui学习笔记--css(常用组件16)--文章页Article

    amazeui学习笔记--css(常用组件16)--文章页Article 一.总结 1.基本使用:文章内容页的排版样式,包括标题.文章元信息.分隔线等样式. .am-article 文章内容容器 .a ...

  9. 【例题 6-11 UVA-297】Quadtrees

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 发现根本不用存节点信息. 遇到了叶子节点且为黑色,就直接覆盖矩阵就好(因为是并集); [代码] #include <bits/ ...

  10. 管理aix的密码策略

    aix 中 /etc/security/user 存放用户的概要 常用参数参数如下 1.account_locked      defines whether the account is locke ...