JNI编程(二) —— 让C++和Java相互调用(2)

来源:互联网 发布:三星s5230c软件 编辑:程序博客网 时间:2024/05/01 11:04

http://chnic.iteye.com/blog/236248

3.getRamdomOrder()

 

这个方法会从backend得到一个随机的Order对象(抱歉这里“Random”拼错了),然后再调用java中相应的通知方法来通知foreground。getRamdomOrder方法没有参数,但是所对应的C++方法里却有两个参数,一定有人会不解。其实细心的朋友一定会发现,JNI里所有对应Java方法的C++ 方法都会比Java方法多两个参数,第一个参数是我们很熟悉的JNIEnv*指针,第二个参数有时是jobject有时是个jclass。针对这第二个参数在这里有必要多废话两句。

 

其实第二个参数传递的是包含了native本地方法的对象或者类对象,我们知道非静态的方法是属于某一个对象的,而静态方法是属于类对象的,所以静态方法可以被所有对象共享。有这个对象/类对象,我们就可以很方便的操作包含了native方法的对象的一些函数了。(这句话有点绕口,没看明白的建议多读两遍)。

 

废话完了言归正传,因为getRamdomOrder不是静态的,所以C++相对应的参数中传递来的是一个jobject对象。

 

Cpp代码  收藏代码
  1. jclass business_class = env->GetObjectClass(obj);  

 

这一句不难理解,GetObjectClass方法可以得到一个对象的类对象,这句有点像Java中的Object.class。不熟悉的朋友建议再去看一下Java反射机制。接下来的几句C++代码应该在之前的方法1和方法2中都解释过。早backend端会发一个“消息”给foreground,之后new一个新的Order类出来。接下来的三句有必要再废话一下。

 

Cpp代码  收藏代码
  1. jfieldID amount_field = env->GetFieldID(order_class, "amount""I");  
  2. jint amount = env->GetIntField(order, amount_field);  
  3. cout << "amount: " << amount << endl;  

 

之前我为Order这个Javabean的amount的属性设置了一个初始值为30,其实就是为了在这里演示如何在C++中拿一个Java对象的属性,拿的方法和我们之前说过的调用Java方法的程序差不多,也要先拿到一个jfieldID,之后调用Get<type>Field方法来取得某一个对象中的某一个属性的数值,最后cout把他打印出来。我们编写测试代码来看一下最终效果。

 

Java代码  收藏代码
  1. Business b = new Business();                   
  2. Order o2 = b.getRamdomOrder();  
  3. System.out.println(o2.getName());  

 

运行上述的测试代码之后,控制台上打出了

 

Got a notification.
amount: 30
Fruit

 

和我们想要的结果是一样的,测试成功。

 

4.analyzeOrder(Order order)

 

这是一个静态方法,foreground会通过这个方法传一个Order的对象到backend去,然后再由CPP端进行“analyze”。在这里我们取出来传递过来的Order对象的name属性,然后打印到控制台上。因为这个方法是静态static方法,所以相对应的C++方法中的第二个参数也变成了jclass对象,也就是Business.class这个类对象。第三个参数是一个jobject对象,很明显就是我们传递过来的order对象。

 

前5句代码应该不难理解,就是调用getName这个方法,然后打印出来。因为JNI的API中并没有提供CallStringMethod这个方法,所以我们用CallObjectMethod这个方法来取得name这个字符串(String很明显也是一个Object),然后再转型成为jstring。也就是下面这句代码。

 

Cpp代码  收藏代码
  1. jstring name_str = static_cast<jstring>(env->CallObjectMethod(obj, getName_method));  
 

取到了name这个字符串之后cout打印出来,之后调用Business这个类对象中的静态方法notificationByStatic来通知foreground。调用的流程以及方法和非静态都是一样的,只不过注意JNI中调用静态方法的API所传递的一个参数是一个jclass而非jobject(这个也不难理解,因为静态方法是属于class类对象的)

 

还是编写测试代码测试这个方法

 

Java代码  收藏代码
  1. Business b = new Business();          
  2. Order o = b.getOrder("Watermelom"100);  
  3. Business.analyzeOrder(o);  
 

控制台上打印出

 

Name in Java_com_chnic_service_Business_analyzeOrder: Watermelom
Got a notification in a static method.

 

第一句是C++中cout打印出来的,第二句则是Java中的静态方法打印出来的,和我们想要的结果是一致的。

 

 

呼~好不容易介绍完了4个方法,最后总结一下吧。

 

  1. JNI中所提供的API远远不止这4个方法中所使用的API。上面介绍的都是比较常用的,本人也不可能罗列出所有的API。
  2. 了解了JNI编程更加有利于深入了解Java中的反射机制,反之亦然。

 

因此如果有对JNI编程有兴趣或者有更深入的需要,可以参考一下sun的相关文档。在这里上传sun提供的JNI的API手册,还有上面例子中所用的演示代码给大家参考。

 

  • Backend.zip (10.2 KB)
  • 描述: CPP代码
  • 下载次数: 234
  • Foreground.zip (3.8 KB)
  • 描述: Java代码
  • 下载次数: 202
  • JNI_API.zip (38.9 KB)
  • 描述: JNI的API参考手册
  • 下载次数: 417

0 0
原创粉丝点击