JNI之------数据类型

文章出处:https://blog.csdn.net/shift_wwx/article/details/25957495

 

其实数据类型,最好的参考资料是jni.h,头文件中定义了一切。

 

首先,补充一下JNI中的一些状态值:

/*
 * Manifest constants.
 */
#define JNI_FALSE   0
#define JNI_TRUE    1

#define JNI_VERSION_1_1 0x00010001
#define JNI_VERSION_1_2 0x00010002
#define JNI_VERSION_1_4 0x00010004
#define JNI_VERSION_1_6 0x00010006

#define JNI_OK          (0)         /* no error */
#define JNI_ERR         (-1)        /* generic error */
#define JNI_EDETACHED   (-2)        /* thread detached from the VM */
#define JNI_EVERSION    (-3)        /* JNI version error */

#define JNI_COMMIT      1           /* copy content, do not free buffer */
#define JNI_ABORT       2           /* free buffer w/o copying back */

 

 

1、void

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

 

2、基本类型

jni.h中是这样定义的:

/* Primitive types that match up with Java equivalents. */
typedef uint8_t  jboolean; /* unsigned 8 bits */
typedef int8_t   jbyte;    /* signed 8 bits */
typedef uint16_t jchar;    /* unsigned 16 bits */
typedef int16_t  jshort;   /* signed 16 bits */
typedef int32_t  jint;     /* signed 32 bits */
typedef int64_t  jlong;    /* signed 64 bits */
typedef float    jfloat;   /* 32-bit IEEE 754 */
typedef double   jdouble;  /* 64-bit IEEE 754 */

可以看出,实际上jni的这些类型就是我们之前c/c++中熟悉的类型,只不过是在jni中有个另外一个叫法而已。

 

注意:typedef并不创建新的类型。它仅仅为现有类型添加一个同义字。例如,jint实际就是int32_t类型,也就是有符号的32位整型。

可以做个图更直观的体现出这些数据类型:

另外,从jni.h中还可以看到这个一个类型:

/* "cardinal indices and sizes" */
typedef jint     jsize;

从jni.h中可以看出以上都是一些基本都是的数据类型,在本地的code中,c或者是c++都是一样的。

 

3、对象类型

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

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


 

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中相同。当最高位被设置时,表示多字节编码。

//调用GetStringUTFChars,把一个Unicode字串转成UTF-8格式字串  
      
Java_com_shift_test_testActivity_test(JNIEnv *env, jobject obj, jstring str)
{
    char buf[128];
    const char *c_str = NULL;
    c_str= (*env)->GetStringUTFChars(env, str, NULL);
    if (c_str == NULL) {
        return NULL;
    }
    printf("%s", c_str);
    sprintf(buff, "hello %s", c_str);
    (*env)->ReleaseStringUTFChars(env, str, c_str);
    
    return (*env)->NewStringUTF(env, buf); 
    
    //或者return (*env)->NewStringUTF(env, "hello world");
}

         上述函数中,有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_com_shift_test_testActivity_test(JNIEnv *env, jobject obj, jstring str)
{
    char outputbuf[128], inputbuf[128];
    int len = (*env)->GetStringLength(env, str);
    (*env)->GetStringUTFRegion(env, str, 0, len, outbuf);
    printf("%s", outputbuf);
    scanf("%s", inputbuf);
    return (*env)->NewStringUTF(env, inbuf);
}

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

 

3.3  GetStringLength/GetStringUTFLength函数简单说明
前者是Unicode编码长度,后者返回的是是UTF编码长度。

 

4、数组类型

JNI对每种数据类型的数组都有对应的函数。
4.1  常见错误操作:

/* 直接操作数组是错误的 */  
Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)  
{
    int i, sum = 0;
    for (i = 0; i < 10; i++) {
	sum += arr[i];
    }
}


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_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
{
    jint buf[10];
    jint i, sum = 0;
    (*env)->GetIntArrayRegion(env, arr, 0, 10, buf);
    for (i = 0; i < 10; i++) {
	sum += buf[i];
    }
    return sum;
}
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_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)  
{ 
    jint *carr;
    jint i, sum = 0;
    carr = (*env)->GetIntArrayElements(env, arr, NULL);
    if (carr == NULL) {
	return 0; /* exception occurred */
    }
    for (i=0; i<10; i++) {
	sum += carr[i];
    }
    (*env)->ReleaseIntArrayElements(env, arr, carr, 0);
    return sum;
}

更多数组操作函数:

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

私房菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值