Android的NDK开发(3)————JNI数据类型的详解

http://blog.csdn.net/luhuajcdd/article/details/7750158

 

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


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



1、void

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


2、基本数据类型





3、对象类型



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

 

[cpp]  view plain copy
  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. }  

 


注意:

 

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


 

[cpp]  view plain copy
  1. //调用GetStringUTFChars,把一个Unicode字串转成UTF-8格式字串<pre name="code" class="cpp">Java_com_conowen_test_testActivity_test(JNIEnv *env, jobject obj, jstring str)  
  2. {  
  3. char buf[128];  
  4. const jbyte *cbyte;  
  5. cbyte= (*env)->GetStringUTFChars(env, str, NULL);  
  6. if (cbyte== NULL) {  
  7. return NULL;  
  8. }  
  9. printf("%s", cbyte);  
  10. (*env)->ReleaseStringUTFChars(env, str, cbyte);  
  11.   
  12. scanf("%127s", buf);  
  13. return (*env)->NewStringUTF(env, buf);  
  14. </pre>//或者return (*env)->NewStringUTF(env, "hello world");<br>  
  15.  }  
  16. <pre></pre>  
  17. <p></p>  
  18. <pre></pre>  
  19. <p></p>  
  20. <p>         上述函数中,有isCopy参数,当该值为JNI_TRUE,将返回str的一个拷贝;为JNI_FALSE将直接指向str的内容。 注意:当isCopy为JNI_FALSE,不要修改返回值,不然将改变java.lang.String的不可变语义。一般会把isCopy设为NULL,不关心Java VM对返回的指针是否直接指向java.lang.String的内容。</p>  
  21. <p>         注意:在调用GetStringChars之后,一定要调用ReleaseStringChars做释放,(Unicode -> UTF-8转换的原因)。不管在调用GetStringChars时为isCopy赋值JNI_TRUE还是JNI_FALSE,因不同JavaVM实现的原因,ReleaseStringChars可能释放内存,也可能释放一个内存占用标记。</p>  
  22. <p></p>  
  23. <span style="font-size:18px; color:#3333FF"><br>  
  24. <br>  
  25. 3.2、GetStringRegion/GetStringUTFRegion函数简单说明</span>  
  26. <p>因为这两个函数不涉及内存操作,所以较GetStringUTFChars使用要简单。也不用进行释放指针之类的操作,非常方便。(推荐使用)</p>  
  27. <p></p>  
  28. <pre name="code" class="cpp"><pre name="code" class="cpp"><pre name="code" class="cpp">Java_com_conowen_test_testActivity_test(JNIEnv *env, jobject obj, jstring str)  
  29. {  
  30.   
  31. char outputbuf[128], inputbuf[128];  
  32. int len = (*env)->GetStringLength(env, str);  
  33. (*env)->GetStringUTFRegion(env, str, 0, len, outbuf);  
  34. printf("%s", outputbuf);  
  35. scanf("%s", inputbuf);  
  36. return (*env)->NewStringUTF(env, inbuf);  
  37. }</pre>  
  38. <pre></pre>  
  39. <pre></pre>  
  40. <p></p>  
  41. <pre></pre>  
  42. <pre></pre>  
  43. <br>  
  44. GetStringUTFRegion有两个主要的参数,start 和 length, 这两个参数以Unicode编码计算. 该函数会做边界检查,所以可能抛出StringIndexOutOfBoundsException。<br>  
  45. <p></p>  
  46. <p><br>  
  47. </p>  
  48. <p><span style="font-size:18px; color:#3333FF"><br>  
  49. </span></p>  
  50. <p><span style="font-size:18px; color:#3333FF"><br>  
  51. </span></p>  
  52. <p><span style="font-size:18px; color:#3333FF">3.3、GetStringLength/GetStringUTFLength函数简单说明</span></p>  
  53. <p><br>  
  54. 前者是Unicode编码长度,后者返回的是是UTF编码长度。<br>  
  55. <br>  
  56. <br>  
  57. </p>  
  58. <p><span style="font-size:24px; color:#FF0000">4、数组类型</span></p>  
  59. <p><img src="https://img-my.csdn.net/uploads/201204/30/1335782694_1137.jpg" alt=""></p>  
  60. <p><br>  
  61. </p>  
  62. <p>JNI对每种数据类型的数组都有对应的函数。</p>  
  63. <p><br>  
  64. </p>  
  65. <p><span style="font-size:18px; color:#3333FF; background-color:rgb(255,255,255)">4.1、常见错误操作:</span><br>  
  66. </p>  
  67. <p></p>  
  68. <pre name="code" class="cpp">/* 直接操作数组是错误的 */  
  69. Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)  
  70. {  
  71. int i, sum = 0;  
  72. for (i = 0; i < 10; i++) {  
  73. sum += arr[i];  
  74. }  
  75. }</pre>  
  76. <p></p>  
  77. <p><span style="font-size:18px; color:#3333FF">4.2、使用void Get<Type>ArrayRegion(JNIEnv *env,<ArrayType> array, jsize start,jsize len, <NativeType> *buf);进行操作</span></p>  
  78. <p>参数说明:</p>  
  79. <p><span style="color:#CC0000">env:</span> the JNIEnv interface pointer.<br>  
  80. <span style="color:#CC0000">array:</span> a reference to an array whose elements are to be copied.将要被拷贝的目标数组<ArrayType><br>  
  81. <span style="color:#CC0000">start:</span> the starting index of the array elements to be copied.(数组的起始位置)<br>  
  82. <span style="color:#CC0000">len: </span>the number of elements to be copied.(拷贝元素的个数)<br>  
  83. <span style="color:#CC0000">buf: </span>the destination buffer.存放结果的本地数组<NativeType></p>  
  84. <p>返回值:void<br>  
  85. </p>  
  86. <p><img src="https://img-my.csdn.net/uploads/201204/30/1335783040_8618.jpg" alt=""><br>  
  87. </p>  
  88. <p></p>  
  89. <pre name="code" class="cpp">Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)  
  90. {  
  91. jint buf[10];  
  92. jint i, sum = 0;  
  93. (*env)->GetIntArrayRegion(env, arr, 0, 10, buf);  
  94. for (i = 0; i < 10; i++) {  
  95. sum += buf[i];  
  96. }  
  97. return sum;  
  98. }</pre><br>  
  99. <br>  
  100. <p></p>  
  101. <p>JNI中数组的基类为jarray,其他如jintArray都是继承自jarray。</p>  
  102. <p></p>  
  103. <p></p>  
  104. <p><span style="font-size:18px; color:#3333FF">4.3、使用<NativeType> *Get<Type>ArrayElements(JNIEnv *env,<ArrayType> array, jboolean *isCopy);进行数组操作</span></p>  
  105. <p></p>  
  106. <p><img src="https://img-my.csdn.net/uploads/201204/30/1335783395_8845.jpg" alt=""></p>  
  107. <p>参数说明:</p>  
  108. <p><span style="color:#CC0000">env: </span>the JNIEnv interface pointer.array: a reference to the primitive array whose elements are tobe accessed.(目标数组)</p>  
  109. <p><span style="color:#CC0000">isCopy: </span>a pointer to a jboolean indicating whether a function</p>  
  110. <p><br>  
  111. </p>  
  112. <p>返回值:返回指向Java数组的一个直接的指针</p>  
  113. <p><br>  
  114. </p>  
  115. <p></p>  
  116. <p><span style="font-size:16px; color:#009900">使用实例:</span></p>  
  117. <p></p>  
  118. <pre name="code" class="cpp">Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)  
  119. {  
  120. jint *carr;  
  121. jint i, sum = 0;  
  122. carr = (*env)->GetIntArrayElements(env, arr, NULL);  
  123. if (carr == NULL) {  
  124. return 0; /* exception occurred */  
  125. }  
  126. for (i=0; i<10; i++) {  
  127. sum += carr[i];  
  128. }  
  129. (*env)->ReleaseIntArrayElements(env, arr, carr, 0);  
  130. return sum;  
  131. }</pre><br>  
  132. )  
  133. <p></p>  
  134. <p><br>  
  135. </p>  
  136. <p>更多数组操作函数:</p>  
  137. <p><img src="https://img-my.csdn.net/uploads/201204/30/1335783812_1174.jpg" alt=""></p>  
  138. <p><br>  
  139. </p>  
  140. <p><span style="font-size:24px; color:#CC0000">5、另外一些有用的宏定义(来自jni.h)</span></p>  
  141. <p></p>  
  142. <pre name="code" class="cpp">#define JNI_FALSE   0  
  143. #define JNI_TRUE    1  
  144.   
  145. #define JNI_VERSION_1_1 0x00010001  
  146. #define JNI_VERSION_1_2 0x00010002  
  147. #define JNI_VERSION_1_4 0x00010004  
  148. #define JNI_VERSION_1_6 0x00010006  
  149.   
  150. #define JNI_OK          (0)         /* no error */  
  151. #define JNI_ERR         (-1)        /* generic error */  
  152. #define JNI_EDETACHED   (-2)        /* thread detached from the VM */  
  153. #define JNI_EVERSION    (-3)        /* JNI version error */  
  154.   
  155. #define JNI_COMMIT      1           /* copy content, do not free buffer */  
  156. #define JNI_ABORT       2           /* free buffer w/o copying back */  
  157. </pre><br>  
  158. <br>  
  159. <p></p>  
  160. <p><br>  
  161. </p>  
  162. <p><br>  
  163. </p>  
  164. <pre></pre>  
  165. <pre></pre>  
  166. <pre></pre>  
  167. <pre></pre>  
  168. <pre></pre>  
  169. <pre></pre>  
  170. <pre></pre>  
  171. <pre></pre>  
  172. <pre></pre>  
  173. <pre></pre>  
  174. <pre></pre>  
  175. <pre></pre>  
  176. <pre></pre>  
  177. <pre></pre>  
  178. <pre></pre>  
  179. <pre></pre>  
  180. <pre></pre>  
  181. <pre></pre>  
  182.   
  183. </pre></pre>  


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值