3.getRamdomOrder()

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

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

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

  1. jclass business_class = env->GetObjectClass(obj);

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

  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把他打印出来。我们编写测试代码来看一下最终效果。

  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。也就是下面这句代码。

  1. jstring name_str = static_cast<jstring>(env->CallObjectMethod(obj, getName_method));

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

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

  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手册,还有上面例子中所用的演示代码给大家参考。

JNI编程(二) —— 让C++和Java相互调用(2)的更多相关文章

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

    自己在外面偷偷的算了下,又有将近两个月没更新过blog了.趁着今天有兴致,来更新JNI编程的第二篇文章.在第一篇里,大概介绍了JNI的特点.用途和优劣.并且做一个最简单的JNI的例子,不过说实话那个例 ...

  2. R语言- 实验报告 - 利用R语言脚本与Java相互调用

    一. 实训内容 利用R语言对Java项目程序进行调用,本实验包括利用R语言对java的.java文件进行编译和执行输出. 在Java中调用R语言程序.本实验通过eclipse编写Java程序的方式,调 ...

  3. Cocos2d-x通过Jni实现C++与Java相互调用

    在cocos2dx项目中与运营平台(java sdk)对接时使用了JNI. 通过C++调用Java 在JniUtil.h文件中如下实现: #ifndef _JNIUTIL_H_ #define _JN ...

  4. 苹果系统开发中的混合编程(2):Swift和C的相互调用

      在进行Swift和C之间的相互调用时,有必要先了解一下两种语言之间的类型转换关系:   C 类型 Swift 类型 bool CBool char, signed char CChar unsig ...

  5. 苹果系统开发中的混合编程(1):Objective-C和C++的相互调用

    首先是OC调用C++的代码.   创建一个Objective-C的项目,并创建c++文件MyCppFile.hpp和MyCppFile.cpp.   把要调用Cpp代码的文件名改成mm后缀名,项目代码 ...

  6. 解析Java的JNI编程中的对象引用与内存泄漏问题

    JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互——在 Java 程序中调用 native ...

  7. 在 JNI 编程中避免内存泄漏

    JAVA 中的内存泄漏 JAVA 编程中的内存泄漏,从泄漏的内存位置角度可以分为两种:JVM 中 Java Heap 的内存泄漏:JVM 内存中 native memory 的内存泄漏. Java H ...

  8. .Net 与 Java 的服务接口相互调用

    本文介绍.Net 与 Java 相互调用的例子.下面的介绍主要包括三方面:一是通过常用Web服务进行相互调用,二是使用TCP/IP套接字进行相互调用,三是使用Remote实现远程对象相互调用. 首先说 ...

  9. 在 JNI 编程中避免内存泄漏与崩溃

    JNI 编程简介 JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互——在 Java 程序中 ...

随机推荐

  1. Aix命令大全

    AIX服务器系统命令简介 在AIX操作系统上有很多的命令.这里介绍一些系统级的命令,它将有助于回答一些常见问题.大家以此做参考,并补充修改. 以下命令在AIX 5.1上测试通过. 正文 以下命令在AI ...

  2. ubuntu修改grub背景

    grub背景由/etc/grub.d/05_debian_theme定义,修改图片只需要将图片文件放到/boot/grub,d/下即可, 修改颜色只需编辑/boot/grub.d/grub.cfg

  3. Linq 中的TakeWhile 和 SkipWhile

    这两个概念容易搞混 理解了一番后 在这里写下便于记忆 SkipWhile 可以理解为如果条件满足  就一直跳过   知道不满足后 就取剩下的所有元素(后面的不会再判断) TakeWhile 可以理解为 ...

  4. CKRule BRMS-决策表使用说明

    决策表的编辑有2个步骤,即规则包编辑.规则数据设置和发布. 1.   规则包编辑 双击CKBoot.exe打开CKRule规则引擎编辑界面.点新建,在左侧的工程窗口中,就会出现一个新的规则包.点击根结 ...

  5. [转]select模型的一种技巧运用-libevent

    参见网址 http://www.cppblog.com/xvsdf100/archive/2013/12/10/204689.html

  6. cetnos 6.7 安装 oracle 11详解

    CentOS 6.7下Oracle 11g安装详解   1. 安装环境 Linux服务器:CentOS 6.7 64位 Oracle数据库版本:Oracle 11gR2 64位 2. 配置修改及参数优 ...

  7. 使用XmlPullParser对xml进行读取

    XML文件是一种标记性语言;在开发中经常在接口交互时被用作报文传输或者把自定义的类序列化为XML的形式存储到数据库.正因为XML文件这么常用,使用JAVA对XML文件进行读写操作是每一个开发人员必须掌 ...

  8. C#基础(五)——类中私有构造函数作用

    如果类成员有private修饰符,就不允许在类范围以外访问这个类成员.对类构造函数应用private修饰符时,则禁止外部类创建该类的实例.尽管看上去有些不好理解(既然不能实例化,那么这个类还有什么用处 ...

  9. PS初始化配置

    前端工程师在使用photoshop之前需要进行一些初始化设置,主要包括以下3个 [1]首选项设置 <ctrl+k> 编辑 > 首选项 > 单位与标尺 > 把标尺和文字的单 ...

  10. vim emmet配置

    http://nerd-is.in/2013-12/learning-vim-again-1-install-vundle/ http://nerd-is.in/2013-12/learn-vim-a ...