19 free(cret);
20 //6. 这里需要手工调用ReleaseStringUTFChars方法,以便Java的垃圾收集器可以回收该资源。
21 env->ReleaseStringUTFChars(format,cformat);
22 return ret;
23 }
3) 编写调用native方法的Java测试代码:
1 public class MyTest {
2 public static void main(String[] args) throws Exception {
3 double price = 44.95;
4 double tax = 7.75;
5 double amountDue = price * (1 + tax / 100);
6 String s = Printf.print("Amount due = %8.2f", amountDue);
7 System.out.println(s);
8 }
9 }
10 /* 输出结果如下:
11 Amount due = 48.43
12 */
4. 带有中文的字符串参数的本地方法:
1) 编写带有native方法的Java代码: 该代码和上面示例中的代码完全相同。
2) 编写与native方法对应的C语言代码:
1 #include "Printf.h"
2 #include
3 #include
4 #include
5 #include
6
7 JNIEXPORT jstring JNICALL Java_Printf_print
8 (JNIEnv* env, jclass cl, jstring format, jdouble x)
9 {
10 //1. 当传递的字符串中包含中文等unicode字符时,推荐使用GetStringChars这一组函数,
11 //当只是包含ASCII的时候,推荐使用上面例子中的GetStringUTFChars那一组函数。
12 //2. 返回Unicode编码的字符串的指针,或者当不能构建字符数组时返回NULL。
13 //直到RelaseStringChars函数调用前,该指针一致有效。
14 //3. 由于Java针对字符串使用了对象池的技术,因此这里一定不能修改返回的const jchar*
15 const jchar* wformat = env->GetStringChars(format,NULL);
16 jchar* wret = (jchar*)calloc(env->GetStringLength(format) + 20,sizeof(jchar));
17 swprintf((wchar_t*)wret,(const wchar_t*)wformat,x);
18 size_t length = wcslen((wchar_t*)wret);
19 //4. 这里需要用JNI提供的NewString方法将本地的unicode字符串构造成jstring。
20 //和Java进行字符串交互时只能使用jstring。
21 jstring ret = env->NewString(wret,length);
22 free(wret);
23 //5. 这里需要手工调用ReleaseStringChars方法,以便Java的垃圾收集器可以回收该资源。
24 env->ReleaseStringChars(format,wformat);
25 return ret;
26 }
3) 编写调用native方法的Java测试代码:
1 public class MyTest {
2 public static void main(String[] args) throws Exception {
3 double price = 44.95;
4 double tax = 7.75;
5 double amountDue = price * (1 + tax / 100);
6 //注意这里的参数字符串中含有unicode字符。
7 String s = Printf.print("Amount due 你好= %8.2f", amountDue);
8 System.out.println(s);
9 }
10 }
5. 编写更为复杂的字符串参数的本地方法:
这个示例代码和上面代码中的主要不同源自C语言部分,本示例使用了JNI提供的GetStringUTFRegion和GetStringRegion,通过预置空间的方式将参数jstring中的字符串数据copy到该预置空间中,因此本例的Java部分代码和上例中Java代码完全相同,这里仅仅给出C语言部分的代码:
1 #include "Printf.h"
2 #include
3 #include
4 #include
5 #include
6
7 JNIEXPORT jstring JNICALL Java_Printf_print
8 (JNIEnv* env, jclass cl, jstring format, jdouble x)
9 {
10 size_t size = env->GetStringLength(format);
11 //1. 这里要求预置的空间大于size * 2.
12 wchar_t wformat[128];
13 memset(wformat,0,sizeof(wformat));
14
15 //2. 通过将jstring中数据直接copy到预置的空间中,则不需要再调用ReleaseStringChars
16 //的方法告诉JVM的垃圾收集器,与此同时该预置的空间在copy之后可以做任何读写操作,
17 //而不像之前用到的GetStringChars和GetStringUTFChars返回的字符串,必须是只读的。
18 //3. 和GetStringChars与GetStringUTFChars的对应关系雷同,JNI还提供了GetStringUTFRegion
19