java jni 入门3 - 字符串参数
来源:互联网 发布:linux查看应用占用内存 编辑:程序博客网 时间:2024/06/05 18:52
参考:《Java核心技术 卷II:高级特性》第12章 本地方法
##################################################################
Java编程语言中的字符串是UTF-16编码点的序列,而C的字符串则是以null结尾的字节序列,所以在这两种语言中的字符串是不一样的。Java本地接口有两组操作字符串的函数,一组把Java字符串转换成"改良的UTF-8"字节序列,另一组将它们转换成UTF-16数值的数组,也就是说转换成jchar数组。
如果你的C代码已经使用了Unicode,你可以使用第二组转换函数。
另一方面,如果你的字符串都仅限于ASCII字符,你可以使用"改良的UTF-8"转换函数
带有字符串参数的本地方法实际上都要接受一个jstring类型的值。带有字符串参数返回值的本地方法必须返回一个jstring类型的值。JNI函数将读入并构造出这些jstring对象。
例如,NewStringUTF函数从包含ASCII字符的字符数组创建一个新的jstring对象,或者是更一般的“改良的UTF-8”编码的字节序列。(使用NewStringUTF方法即可)
以下是对NewStringUTF函数的一个调用:
JNIEXPORT jstring JNICALL Java_HelloNative_getGreeting(JNIEnv *env, jclass cl) {jstring jstr;char greeting[] = "Hello, Native World!";jstr = (*env)->NewStringUTF(env, greeting);return jstr;}
所有对JNI函数的调用都使用到了env指针,该指针是每一个本地方法的第一个参数。env指针是函数指针表的指针。所以,必须在每个JNI调用前面加上(*env)->,以便实际上取消对函数指针的引用。而且,env是每个JNI函数的第一个参数。
note:C++中对JNI函数的访问要简单一些。JNIEnv类的C++版本有一个内联成员函数,它负责帮你查找函数指针。故调用方式为:
jstr = env->NewStringUTF(greeting)注意,这里从该调用的参数列表里删掉了JNIEnv指针
NewStringUTF函数可以用来构造一个新的jstring,而读取现有jstring对象的内容,需要使用GetStringUTFChars函数。该函数返回指向描述字符串的"改良UTF-8"字符的const jbyte*指针。
note:具体的虚拟机可以自由地选择该编码来表示它内部的字符串。所以,你可以得到实际的Java字符串的字符指针。因为Java字符串是不可变的,所以慎重处理const就显得非常重要,不要试图将数据写到该字符数组中。
另一方面,如果虚拟机使用UTF-16或UTF-32字符作为其内部字符串的表示,那么该函数会分配一个新的内存来存储等价的“改良UTF-8”编码字符。
虚拟机必须知道何时使用字符串,这样就能进行垃圾回收(垃圾回收器是在一个独立线程中运行的,它能够终端本地方法的执行)。基于这个原因,必须调用ReleaseStringUTFChars函数。
另外,可以通过调用GetStringRegion或GetStringUTFRegion方法来提供自己的缓存,以存放字符串的字符。
函数GetStringUTFLength函数返回编码字符串所需的"改良UTF-8"字符个数。
以C代码访问Java字符串
jstring NewStringUTF(JNIEnv *env, const char bytes[])根据以全0字节结尾的“改良UTF-8”字节序列,返回一个新的Java字符串对象,或者当字符串无法构造时,返回NULL
jsize GetStringUTFLength(JNIEnv *env, jstring string)
返回进行UTF-8编码所需的字节个数(不计算作为终止符的全0字节)
const jbyte* GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy)返回"改良UTF-8"编码的字符串的指针,或者当不能构建字符数组时返回NULL。直到ReleaseStringUTFChars函数调用前,该指针一直有效。isCopy指向一个jboolean,如果进行了复制,则填入JNI_TRUE,否则填入JNI_FALSE。
void ReleaseStringUTFChars(JNIEnv *env, jstring string, const jbyte bytes[])通知虚拟机本地代码不再需要通过bytes(GetStringUTFChars返回的指针)返回Java字符串
void GetStringRegion(JNIEnv *env, jstring string, jsize start, jsize lengh, jchar *buffer)将一个UTF-16双字节序列从字符串复制到用户提供的尺寸至少大于2xlength的缓存中。
void GetStringUTFRegion(JNIEnv *env, jstring string, jsize start, jsize length, jbyte *buffer)将一个"改良UTF-8"字符序列从字符串复制到用户提供的缓存中。为了存放要复制的字节,该缓存必须足够长。最坏情况下,要复制3xlength个字节。
jstring NewString(JNIEnv* env, const jchar chars[], jsize length)根据Unicode字符串返回一个新的Java字符对象,或者在不能创建时返回NULL
参数:env JNI接口指针
chars 以null结尾的UTF-16字符串
length 字符串中字符的个数
jsize GetStringLength(JNIEnv *env, jstring string)返回字符串中字符的个数。
const jchar* GetStringChars(JNIEnv *env, jstring string, jboolean *isCopy)返回Unicode编码的字符串的指针,或者当不能构建字符数组时返回NULL。直到ReleaseStringChars函数调用前,该指针一直有效。isCopy为NULL或者是指向JNI_TRUE填充的jboolean,否则,它指向JNI_FALSE填充的jboolean.
void ReleaseStringChars(JNIEnv *env, jstring string, const jchar chars[])通知虚拟机本地代码不再需要通过chars(GetStringChars返回的指针)返回Java字符串。
##########################################################################################3
使用带有本地sprint方法的类
格式化浮点数的C函数原型如下:
JNIEXPORT jstring JNICALL Java_Printf2_sprint(JNIEnv *env, jclass cl, jstring format, jdouble x)
printf2Test.java
/** * @time 15-11-10 * @author zj**/class Printf2Test {public static void main(String[] args) {double price = 44.95;double tax = 7.75;double amountDue = price * (1 + tax / 100);String s = Printf2.sprint("Amount due = %8.2f", amountDue);System.out.println(s);}}
Printf2.java
/** * @time 15-11-10 * @author zj**/class Printf2 {public static native String sprint(String format, double x);static {System.loadLibrary("Printf2");}}
printf.c
/** * @time 15-11-10 * @author zj*/#include "Printf2.h"#include <stdio.h>#include <stdlib.h>#include <string.h>JNIEXPORT jstring JNICALL Java_Printf2_sprint (JNIEnv *env, jclass cl, jstring format, jdouble x) {const char* cformat;jstring ret;cformat=(*env)->GetStringUTFChars(env, format, NULL);char* cret;cret = (char*)malloc(strlen(cformat)+8);sprintf(cret, cformat, x);ret = (*env)->NewStringUTF(env, cret);free(cret);(*env)->ReleaseStringUTFChars(env, format, cformat);return ret;}
注意,通过调用GetStringUTFChars来读取格式参数,通过调用NewStringUTF来产生返回值,通过调用ReleaseStringUTFChars来通知虚拟机不再需要访问字符串。
- java jni 入门3 - 字符串参数
- java jni 入门2 - 数值参数与返回值
- 【java&&jni】jni入门篇
- java JNI入门一
- JAVA jni入门
- java JNI入门
- java jni 初步入门
- Android JNI入门第二篇——Java参数类型与本地参数类型对照
- JNI入门二:字符串和字符串数组
- Java之JNI参数传递
- java类作为JNI参数
- JNI字符串参数传递与返回值
- android(NDK+JNI)---JNI字符串参数传递与返回值
- java调用vc6写的dll - 关于jni应用中的字符串参数传递
- JAVA->JNI 传递字符串数组
- android-jni与java参数传递
- android-jni与java参数传递(续集)
- JNI中的java类参数传递
- 快速排序
- android获得sd卡和本机内存大小
- android jni签名验证(二)
- 关于Android Studio使用Gradle多渠道打包的一些记录
- jquery简单的选项卡
- java jni 入门3 - 字符串参数
- 使用JSON格式传递数据,获取JSON的值
- matplotlib中legend位置调整
- add column时default null的问题
- 杭电1037——Keep on Truckin'(简单题)
- Android换色、主题和样式
- IOS中的instancetype和id关键字
- 软件工程师考试总结
- 面向对象基本元素和基本原则