Step By Step(Java 本地方法篇) (三)

2014-11-24 03:21:35 · 作者: · 浏览: 7
ing ret = env->NewStringUTF(cret);

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