c++工程与java的互相调用

来源:互联网 发布:淘宝网中老年运动套装 编辑:程序博客网 时间:2024/06/06 04:03

JNI简介
  
JNI:Java Native Interface,是Java语言提供的一种通用接口,用于Java代码与本地化代码的交互。所谓本地化代码是指直接编译成的与机器相关的二进制代码,而非Java字节码之类的中间代码。Windows下面的可执行文件,DLL等,Linux下面的可执行文件和SO文件等,都是二进制代码。
  JNI允许Java语言编写的程序与其他语言编写的程序库(DLL, SO)或可执行文件进行互操作,包括汇编、C、C++。JNI产生的原因在于以下几种需求:
  (1)、你的应用程序需要使用系统相关的功能,而Java代码不支持或是难以办到。这个比较典型的是实现托盘图标,有几种现成的方案都是用的JNI做的,名字好像是叫做TrayIcon和StayOnTop。当然啦,如果是用的Java1.6,那就要另当别论了。
  (2)、已有其他语言写好的类库或程序,希望Java程序可以使用它们。
  (3)、出于更高的性能要求,希望使用汇编或是C/C++语言来实现部分功能。
  下图出自JNI Tutorial,展示了JNI的地位:

以上参考自http://blog.csdn.net/chenjin_zhong/article/details/5870305

 

一.C++调用JAVA工程

这部分的内容详见我上传的资源文档《c++调用java工程总结》,在此不再赘述!

 

二. JAVA调用C++

主要分为以下几个步骤:

1.在java类中编写native方法

这一步很简单,就是在java类中写一个带native关键字的函数,比如:public native int buildTripleToIndexBin(String strPredFile1,  String strPredFile2,
   String strUriFile, String strTripleFile, String strOutTripleBin,  String strOutUriBin);

 

2.编译java工程生成class文件

这一步也很简单,特别是如果用的eclipse开发环境,就不必去命令行窗口下运行javac命令了,只需要“debug”或者“run”就可以得到对应的class文件。

 

3.利用javah命令处理类文件,生成c++头文件

这一步非常关键,也非常容易出错。下面用个例子说明一下:

我的java工程所在目录:E:\SVN\src\source\Video_Ont_Build

这是eclipse自动管理的工程目录,需要说明的只有src目录和bin目录。其中src目录下存放的所有的包以及包下面的java文件,每个包及其下面的文件都是一个目录;src目录下存放的所有的包以及根据包下面的java文件生成的对应的class文件,每个包及其下面的class文件都是一个目录。我们需要做的是切换到bin目录下进行反编译

生成对应的c++头文件。

好了,说明到此为止,现在打开命令行,切换到相应的目录下:

然后执行命令:

javah -classpath .;D:\eclipse_install_lib\apache-jena-2.7.4\lib\jena-core-2.7.4.jar VideoOntology.VideoOntBuilder

注意一下-classpath参数,表示从中加载类的路径,多个路径中间用;隔开,并且也要设置引用的外部jar包的路径。

该命令运行完之后就可以在bin目录下得到c++头文件,我这里是VideoOntology_VideoOntBuilder.h。

 

4.使用C++实现native方法,编译成动态库dll文件

首先到java安装目录下的jdk目录下的include目录下拷贝jni.h和win32/jni_md.h到c++工程目录下,并且将上一步生成的VideoOntology_VideoOntBuilder.h也拷贝到c++工程目录下,如图:

然后开始实现c++工程中的本地方法:

实现完之后将对应的c++工程编译成dll文件,并放到jdk安装目录的bin目录下,比如:D:\ProgramSoftware\java7-x64\jdk\bin。或者放到C:\Windows\System32目录下也行,两个都可以。

这里比较让我困惑的是,我在函数的开头调用GetStringUTFChars函数得到转换的c++字符串,然后在函数的最后调用ReleaseStringUTFChars释放这部分的内存,在程序运行的的时候竟然报错:

#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# E:\SVN\src\source\Video_Ont_Build\hs_err_pid4876.log
#
# If you would like to submit a bug report, please visit:
#  
http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

然后我把ReleaseStringUTFChars这部分行去掉,竟然不报错,非常诡异啊。按理说我一开始申请了字符串的内存,使用完之后释放这部分内存,这应该是正确的使用内存的步骤,不然可能出现内存泄露。但是这里竟然“不让”释放内存,为毛啊,不解中。。。。

 

5.在java中加载生成的dll文件,调用c++本体方法

在java类下添加代码:

static {
  System.loadLibrary("VQAIndex");
 }

VQAIndex就是上一步生成的动态库文件,这里不需要写dll,系统会自动添加后缀.dll!!

最后就是在java类中调用本体方法了,并且“run”,等待JAVA程序执行

就会看到java程序开始调用c++代码喽,哈哈!!