参考来源:
http://blog.sina.com.cn/s/blog_b37338430101f3zq.html
http://www.cnblogs.com/xiaocainiao2hao/p/5619862.html
https://blog.csdn.net/aslgm_1/article/details/71514617
【huachao1001的专栏:http://blog.csdn.net/huachao1001/article/details/53906237】
本文环境:IntelliJ idea2018.2+Visual Studio 2017
项目:JavaWEB+Win32控制台
声明:本人是个新手小白。因为项目是C++算法写的,但是要用网页调用,所以先学习JavaWEB调用C++程序作为尝试。参考了网上的一些教程,结合自己的理解与出现的错误,写成总结日后参考。不足之处请提出。
首先明确本文的步骤:
- 在Java中新建一个类。
- 生成JNI头文件。(此处有两种方法:2.1手动输入javah命令生成头文件、2.2 一键生成头文件)
- 在VS2017下引入头文件。
- 将dll添加进JavaWEB工程,成功运行。
利用IntelliJ idea新建一个Java工程,在src中新建一个Java类,名称命名“testNative”。之后弹出testNative.java。
在testNative.java中写如下程序:
函数System.loadLibrary()是加载dll(windows)或so(Linux)库,只需名称即可,无需加入文件名后缀(.dll或.so)。
native关键字将函数sayHello()声明为本地函数,由C/C++实现。具体的实现就在hello.dll(Windows平台)或hello.so(Linux平台)中。
JNI生成头文件是通过JDK中提供的javah来完成,javah在 {JDKHome}/bin
目录中。用法如下:
javah -jni -classpath (搜寻类目录) -d (输出目录) (类名)
例如,将E:\Porject\out\com\huachao\java
目录中的HelloJNI.class
生成头文件,并放入到E:\Project\jni
中:
javah -jni -classpath E:\Porject\out\com\huachao\java -d E:\Project\jni com.huachao.java.HelloJNI.java
需要注意的是,使用javah来生成头文件(.h)时,-classpath指定的是编译后的java文件(.class)的目录,而不是源文件(.java)的目录,因此在使用javah指令之前,先build一下项目(或直接运行一下)。此时会生称out目录,所有编译后的文件都会存放在这个目录中。
Build之后:project下的out中多出来production及以下内容。
生成out目录之后的:
接下来,直接在IDEA的Terminal窗口运行javah,写命令如下:
(没有Terminal窗口的可以在File→Plugins→Terminal 勾选它,点击Apply,点击Restart即可
如果是要启动terminal则必须先做完上面动作,才可以点击Tools→Open Terminal... 来达到打开terminal)
javah -jni -classpath (搜寻类目录) -d (输出目录) (类名)
按回车键运行,在终端(Terminal)输入如上命令之后,目录出现了jni文件夹,下面对应有头文件。
打开testNative.h, 函数名称是有规律的,即Java_<
包
>_<
类名
>_<
函数名
>
至此,生成头文件的第一种方法就结束了。还有另一种一键生成的方法更简单请往下看。
如果目录层次很深,或者是有多个需要生成头文件的class文件,这工作量太大了,当然你可以通过写个小程序来实现。
但是这里有个更便捷的方法。点击File>Settings>Tools>External Tools
:
添加一个新的External Tools:
在testNative.java文件中 点击右键>External Tools>Generate Header File
,
点击生成,可以看到Terminal窗口会自动运行指令。跟2.1小节的指令一模一样。
首先打开Visual Studio 2017,新建一个Win32控制台。
Win32项目现在位于“新建项目”对话框中的Windows桌面类别下面,在此类别下面还有一个新的Windows桌面向导,可以创建新的Win32项目
双击 Windows桌面向导,打开如下
注意此处不要勾选预编译标头。
初始目录:
拷贝三个.h文件到VS项目中:
将在Java JDK的安装目录下,我的目录为C:\Program Files\Java\jdk1.8.0_181\include下的jni.h,
与C:\Program Files\Java\jdk1.8.0_181\include\win32下的jni_md.h,
与第一步生成的testNative.h, 一共三个头文件,拷贝到当前VS项目目录下,拷贝之后的目录为:
将testNative.h中的 #include
在源文件目录下新建.cpp文件,起名main.cpp。写入程序:
#include "testNative.h"
#include "jni.h"//注意添加这句
#include
using namespace std;
JNIEXPORT void JNICALL Java_testNative_sayHello(JNIEnv *env, jobject obj)
{
cout << "Hello World!" << endl;
cout << "I come from C++!" << endl;
}
另外,注意,在右侧目录中 右击 解决方案-配置管理器
将Debug改成64位,因为我的IntelliJ idea是64位下的。这样改动之后生成的dll可以用在64位平台下。
之后按F5运行,运行成功如图所示。
显示生成的dll的路径。找到此dll,复制。
将复制得到的dll改名为“hello.dll”,将其拷贝到JavaWeb项目目录下,如图所示:
之后运行项目,可以在控制台输出中看到如下图所示结果,表示成功。
1.【注意事项】:如果你建的C++工程时32位的,当然Win32就是32位的工程,生成的dll只能运行在32位的JDK上。如果你的Java JDK是64位的,那么你新建Win32控制台程序后,在项目属性中修改平台为64位即可。若不修改,出现如下错误:
2.第一次新建Win32控制台选择了预编译表头,如下图所示:
在写main.cpp时候运行出现如下错误:
注意不勾选 预编译标头。
3.【注意事项】将testNative.h中的#include
写在最后:新手起步,不断学习总结。参考了网络资料,有问题提出大家共同交流!
转载请注明出处,谢谢^_^