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. Flask项目之手机端租房网站的实战开发(十三)

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...

  2. windows和Linux内存的对齐方式

    一.内存对齐的初步解说 内存对齐能够用一句话来概括: "数据项仅仅能存储在地址是数据项大小的整数倍的内存位置上" 比如int类型占用4个字节,地址仅仅能在0,4,8等位置上. 例1 ...

  3. Android学习之图片压缩,压缩程度高且失真度小

    曾经在做手机上传图片的时候.直接获取相机拍摄的原图上传,原图大小一般1~2M.因此上传一张都比較浪费资源,有些场景还须要图片多张上传,所以近期查看了好多前辈写的关于图片处理的资料.然后试着改了一个图片 ...

  4. iOS_06_基本运算符

    一.算术运算 c语言一共有34种运算符,包括了常见的加减乘除 1.加法运算+ # 除了能做加法运算,还能表示正号:+5.+90 2.减法运算- # 除了能做减法运算,还能表示符号:-10.-200 3 ...

  5. POJ 2376 Cleaning Shifts 区间覆盖问题

    http://poj.org/problem?id=2376 题目大意: 给你一些区间的起点和终点,让你用最小的区间覆盖一个大的区间. 思路: 贪心,按区间的起点找满足条件的并且终点尽量大的. 一开始 ...

  6. Web自动化测试 Selenium+Eclipse+Junit+TestNG+Python

    Selenium+Eclipse+Junit+TestNG+Python 第三步 下载Selenium IDE.SeleniumRC.IEDriverServer.SeleniumClient Dri ...

  7. set_fix_multiple_port_nets

    set_fix_multiple_port_nets   -all    -buffer_constants 加上这个命令之后 综合之后的网表就不会出现assign语句 否则会出现

  8. mahout測试朴素贝叶斯分类样例

    对于这个測试建议大家先理解原理,这里我画了例如以下的示意图 接下来就依照例如以下的细节来输入指令測试: 首先前提是Hadoop安装并启动,mahout已经安装了. <strong>< ...

  9. android 蓝牙各种UUID

    ServiceDiscoveryServerServiceClassID_UUID = '{00001000-0000-1000-8000-00805F9B34FB}' BrowseGroupDesc ...

  10. C# 获取文件路径,读取项目中某程序集下文件

    获取文件路径 ------------------------------------------------------------------------- winform获取文件路径: stri ...