`
chnic
  • 浏览: 227945 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

    博客分类:
  • Java
阅读更多

3.getRamdomOrder()

 

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

 

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

 

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

 

jclass business_class = env->GetObjectClass(obj);

 

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

 

	jfieldID amount_field = env->GetFieldID(order_class, "amount", "I");
	jint amount = env->GetIntField(order, amount_field);
	cout << "amount: " << amount << endl;

 

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

 

		Business b = new Business();				 
		Order o2 = b.getRamdomOrder();
		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。也就是下面这句代码。

 

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

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

 

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

 

		Business b = new Business();		
		Order o = b.getOrder("Watermelom", 100);
		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代码
  • 下载次数: 247
  • JNI_API.zip (38.9 KB)
  • 描述: JNI的API参考手册
  • 下载次数: 436
分享到:
评论
2 楼 woaigislijk 2009-02-02  
非常好,大侠,希望继续努力!!
1 楼 avi2 2009-01-06  
我在C++中使用了堆栈
报了一个这样的错误
An unrecoverable stack overflow has occurred.
不知道楼主是否遇到过,这样的问题如何解决

相关推荐

    安卓Android源码——调用C++代码和C++代码调用源码.zip

    总结来说,Android调用C++代码和C++调用Java源码是通过JNI实现的,涉及到Android.mk或CMakeLists.txt的配置、JNI函数的编写以及内存管理等多个方面。正确理解和运用这些知识,能帮助开发者充分利用Android的本地层...

    Android源码——调用C++代码和C++代码调用源码.zip

    在提供的压缩包文件中,1_120818224513_1.png和1_120818224513_2.png可能是示例代码或步骤截图,而"Android 调用C++代码和C++代码调用源码"这个文件可能包含了具体的代码示例。读者可以通过查看这些资源进一步理解和...

    安卓Android源码——代码调用C++代码和C++代码调用代码.zip

    JNI编程中错误处理非常重要,因为Java层可能无法捕获C++的异常。使用`__android_log_print`进行日志输出有助于调试。 总结,本资料包通过示例详细展示了Android应用如何通过JNI调用C++代码以及C++代码如何反向调用...

    JNI编程指南书

    ### JNI编程指南书知识点概述 #### 一、JNI的基本概念及应用场景 JNI(Java Native Interface)作为Java平台的重要组成部分,其核心价值在于能够使Java程序有效地利用现有的C/C++代码,进而实现性能优化或功能扩展...

    JNI攻略之十一――启动虚拟机调用java类

    标题与描述均指向了一个具体的技术主题——通过JNI(Java Native Interface)在C语言环境中启动Java虚拟机并调用Java类。这一技术应用广泛,尤其是在需要跨语言编程或利用Java的特性(如垃圾回收、多线程)而底层...

    java调用C语言编写的so库中的函数,java调用C语言编写的dll库中的函数

    总的来说,Java调用C语言编写的本地库需要理解JNI和JNA的工作原理,以及它们如何处理数据类型转换、参数传递和本地库的加载。通过这些技术,开发者可以充分利用C/C++的性能优势,同时享受Java的平台独立性和高级抽象...

    jni例子——使用int数组

    在这个“jni例子——使用int数组”的示例中,我们将深入探讨如何在Java和C/C++之间传递和操作int数组。 1. **JNI基础知识**: - JNI接口提供了Java与本地代码(如C/C++)通信的桥梁,使得开发者可以在Java应用中...

    C++与Java混合编程

    1. **JNI (Java Native Interface)**:这是Java提供的一种标准接口,允许Java代码调用本地方法(如C/C++函数)。通过JNI,开发者可以在Java程序中嵌入C++代码以利用其高性能特性。 2. **JNA (Java Native Access)*...

    java C#相互调用的全新方式

    本文将深入探讨“Java与C#相互调用的全新方式”,结合给定的标签“源码”和“工具”,我们将重点讨论如何通过中间件或接口实现这种交互,并提供一种可能的解决方案——AMFCall。 Java和C#的互操作性通常通过以下几...

    Java中JNI的使用(一)——native

    Java中的JNI(Java Native Interface)是一种技术,允许Java代码与其他编程语言编写的代码进行交互,尤其是C和C++。JNI在许多场景下是必要的,比如访问操作系统特定的功能、提升性能或者利用已有的C/C++库。这篇博客...

    Java通过调用C/C++实现的DLL动态库——JNI的方法

    Java Native Interface(JNI)是一种Java平台的标准接口,它允许Java代码和其他编程语言(如C/C++)编写的代码进行交互。在本示例中,Java程序通过JNI调用了C/C++实现的DLL(动态链接库)来执行特定的数学运算。以下...

    java通过JNI调用dll的事例 附说明

    Java编程语言虽然强大,但在某些特定情况下,如与操作系统底层交互或者使用已有的C/C++库时,我们可能需要借助JNI(Java Native Interface)来调用本地代码,比如DLL动态链接库。本教程将深入讲解如何使用Java通过...

    C++Java 如何呼叫Matlab 所提供的函数

    - **JNI**: 编写 JNI 接口,让 Java 可以调用这个 C++ 函数。 #### 2. Java 代码示例 ```java public class MatrixInverse { static { System.loadLibrary("MatrixInverse"); } public native void ...

    由浅入深——Java 2自学教程 配书光盘.rar

    配书光盘中的“由浅入深——Java 2自学教程 配书光盘.rar”压缩包文件,包含了书中所有工程素材和源码,这对于读者实践和理解Java编程概念至关重要。 Java 2,也被称为Java 2平台标准版(J2SE),是Java语言的一个...

    Java调用C++

    总之,Java调用C++主要依赖于JNI技术,通过JNI,开发者可以在Java应用中充分利用C++的高效性能和丰富的库资源。这涉及到Java端的接口声明、C++端的实现以及动态库的加载。通过分析提供的示例工程,你可以更深入地...

    安卓Android源码——java调用C例子.zip

    本资料“安卓Android源码——java调用C例子.zip”聚焦于如何在Android应用中通过Java调用C语言编写的原生代码,这一过程通常称为JNI(Java Native Interface)。 JNI是Java平台标准的一部分,它允许Java代码和其他...

Global site tag (gtag.js) - Google Analytics