17年写过一次jni操作一直给认识的小伙伴说怎么怎么操作 最近发现又有人问起 到处发pdf给他们 发现有点麻烦现在就干脆放在网上大家看

 

JNI dll基础使用

javaJNI使用和DLL动态链接库的使用,和lib静态链接库的使用

1.所需工具

工具:eclipse

C++/C编译环境 :MinGw

C++/C开发工具:eclipse 集成插件CDT

CDT:下载地址:http://www.eclipse.org/cdt/downloads.php

MinGw:下载地址:http://download.csdn.net/download/piano7heart/3651248

JDK使用任意版本都可以

2.环境搭建

jdk 的环境就不需要再提了

MinGw:环境部署

这里我推荐绿色版的MinGw    所谓的绿色版就是别人下载好的包

打开系统环境变量:

新建 MINGW_HOME

路径为你MinGw的路径 例:E:\mingw

PATH添加 %MINGW_HOME%/bin

打开控制台 输入 gcc -v

JAVA JNI操作

能够查看到版本号就说明MinGw环境搭建好了

因为我们是使用MinGw来编写C/C++的代码 也就是gcc

所以我这边使用的是eclipse 的CDT插件:

下载好CDT之后

打开eclipse

JAVA JNI操作

选择Help

JAVA JNI操作

选择安装一个新的插件

JAVA JNI操作

点击 Archive

JAVA JNI操作

JAVA JNI操作

这里我们演示选择cdt9.2版本

JAVA JNI操作

选择确定之后将会出现如下界面,因为不是网络版我们可以选择全部安装也可以只安装CDT的C++组件 这里我选择全部安装勾上之后:等待安装完成

JAVA JNI操作

因为我这里以前安装的版本是8.0的现在安装9.0以上的提示

JAVA JNI操作

这个我们选择第一个不改变我以前的设置直接安装就好了

一路next出现如下界面的时候

JAVA JNI操作

选择第一个 接收许可条款

点击Finish

JAVA JNI操作

安装完成之后eclipse显示如下界面点击OK就可以重启了

JAVA JNI操作

JAVA JNI操作

yes 重启

重启之后我们查看插件是否安装 成功

最直接的展示就是点击file

JAVA JNI操作

选择Othe

JAVA JNI操作

搜索c++ 因为我们是要使用C++ 来跟JNI操作

9.0以上的版本跟8.0版本的不一样新建C++项目的时候一定要注意

JAVA JNI操作

安装9.0的版本新建的时候可能出现如下界面这个时候把下面的那个勾取消掉

JAVA JNI操作

取消掉之后将会出现如下界面选择第一个Executable

JAVA JNI操作

选择创建一个HelloWorldC++ 项目 使用的编译器选择MinGw GCC  因为我们安装的就是MinGw然后随便取个名字这里我叫TestCdt

JAVA JNI操作

新建之后将会出现如下界面效果

然后打开工程

JAVA JNI操作

这个时候不是完整的项目我们需要编译注意:每次写完想要执行都需要编译选中我们的TestCdt

JAVA JNI操作

默认小锤子图标是选中Debug直接点击编译

JAVA JNI操作

这里是完整的工程Debug文件夹里面将会有一个exe结尾的可执行文件,控制台显示的是gcc  编译cpp的命令 提醒一下在CDT里面 cpp的编译文件是.o结尾的  相当于 java的.class文件

JAVA JNI操作

源文件.o结尾

然后我们可以运行我们的第一个CDT 程序

JAVA JNI操作

JAVA JNI操作

这里说明环境搭建完成了

现在我们就需要知道JNI的基础使用

3.JNI基础使用:

首先我们需要建立一个java工程

JAVA JNI操作

JAVA JNI操作

JAVA JNI操作

新建TestJni 工具类

我们就使用C++打印: 我的第一个JNI

创建JNI接口

JAVA JNI操作

注意使用JNI接口必须创建native 接口然后我们需要根据这个接口生成C++的头文件.h文件

这里我们使用java的一个命令   javah -JNI这个命令

首先打开cmd

JAVA JNI操作

找到你的工程目录

JAVA JNI操作

javah -jni 包名.接口类然后刷新你的工程

JAVA JNI操作

你会发现在你的工程下面会出现一个.h的头文件

JAVA JNI操作

打开你就会发现有个函数接口

JNIEXPORT 这句话是必须要加的,因为我们是jdk自动生成的这个我们就不需要自己操作了

意思就是我们的这个函数是要给JNI使用的, 在上面有extern “C”意思就是可以给C使用

我们的这个头文件引入了jni.h这个头文件很明显,这个是使用JNI来实现 跨平台调用的

然后我们复制这个文件

到我们开始新建的那个C++工程中

JAVA JNI操作

复制到C++工程的src下

JAVA JNI操作

打开我们的TestCdt.cpp

现在我们需要实现我们的方法

JAVA JNI操作

引入我们想要实现的JNI头文件

JAVA JNI操作

我们需要在cpp中实现这个函数这里我就简单打印 我的第一个JNI工程

JAVA JNI操作

然后点击项目

JAVA JNI操作

JAVA JNI操作

点击add选择jdk路径下的includes

JAVA JNI操作

JAVA JNI操作

选中完成之后点击Apply  ok

然后我们需要生成DLL提供给java使用

JAVA JNI操作

JAVA JNI操作

选择第一个

JAVA JNI操作

JAVA JNI操作

选中

JAVA JNI操作

-Wl,--add-stdcall-alias   加入这句话

点击Apply ok

然后编译

JAVA JNI操作

编译之后生成DLL文件

复制该文件 到你的jdk/bin 路径下  和 jdk/jre/bin  路径下这俩个路径都要放置

然后打开java工程

JAVA JNI操作

新建一个test 创建main方法测试

JAVA JNI操作

引用DLL

JAVA JNI操作

测试是否成功

JAVA JNI操作

这样就说明测试成功了

4.调用动态链接库

打开刚才的CPP工程 现在我们要使用别人提供的dll

这里以 身份证SDK做演示

JAVA JNI操作

复制sdtapi.dll   sdtapi.h  savephoto.dll dewlt.dll

JAVA JNI操作

如下结构放置

在原有的基础上引入sdtapi.h

JAVA JNI操作

然后引入DLL依赖  在Cpp里面引入链接库 跟java的区别是java是jar文件 CPP是lib文件

JAVA JNI操作

把lib文件复制进去

JAVA JNI操作

然后配置引用

JAVA JNI操作

右键项目 Properties

JAVA JNI操作

输入依赖的lib的名称点击ok大小写不分但是建议你填的的时候区分开来,记住不要带后缀

JAVA JNI操作

然后点击下面的路径这里是寻找lib的路径在什么位置,因为我们已经把lib复制进入我们的工程了,所以我们直接

JAVA JNI操作

JAVA JNI操作

选择我们的工程我们是复制在Debug这个文件夹下面的直接选择

JAVA JNI操作

OK

JAVA JNI操作

这样就可以了然后我们写java接口

打开我们的java工程

JAVA JNI操作

新加一个接口我们看看文档

JAVA JNI操作

我们要使用这个接口

JAVA JNI操作

我们要使用JNI开始使用它

如上操作同过javah -jni命令生成头

然后复制进cpp工程里面我们要实现这个函数

JAVA JNI操作

我们要实现它

JAVA JNI操作

这个简单的接口我们就写好了现在我们点击小锤子编译

JAVA JNI操作

编译完成现在我们使用这个DLL测试接口是否编译成功

复制dll到

JAVA JNI操作

jdk/bin 和jdk/jre/bin

JAVA JNI操作

我们在java这边来测试这个接口

JAVA JNI操作

JAVA JNI操作

这里说明调用成功如果有硬件设备就会检测到返回结果为1

**********************************************************

这里将说明在另一种情况下的DLL使用:

很多时候可能遇到的接口情况是  我们可能说没有什么lib库的提供,意思就是说可能别人提供的文件只有.h  和DLL连个文档都没有这个时候我们该怎么办

这个时候我们就需要一个东西 类似java  JNI调用DLL一样的东西  我们将通过CPP获取DLL句柄

这里我就直接帖代码   前面已经说了JNI如何使用我就在这里 不废话了

首先我们声明一个接口

JAVA JNI操作

现在我们要直接使用DLL 复制DLL  只需要DLL就行了 其他的都不需要  包括头

JAVA JNI操作

我们主要使用的DLL就是sdtapi

现在我们要使用他

来使用他

JAVA JNI操作

这是我们实现的代码

这里我引用了  windows.h的头文件也就是说  我这里使用了win32的接口来实现操作  ,然后按照流程引用JNI的接口

然后实现JNI函数 

JAVA JNI操作

我们通过LoadLibray();这个函数     获取DLL句柄 这个函数接收的是DLL路径   这里我直接放在项目Debug目录下 所以可以直接引用  这个函数返回的是句柄  HINSTANCE  返回的错误结果是 NULL 注意 ,cpp里面没有null只有NULL 获取句柄之后我们需要干什么, 我们需要声明,声明实现函数,这个实现函数就是DLL里面的函数接口  这里我们实现一个函数

typedef int (*InitComm)(int port);     声明函数指针 InitComm   我们要通过句柄获取函数

InitComm   initComm;                                           

initComm=(InitComm)GetProcAddress(hInstLibrary,"InitComm");

这里 返回的结果也是是否非空  返回 NULL就说明没有获取到当前函数   这个GetProcAddress函数 就是获取函数接口 通过句柄  指针函数名获取指定函数 然后获取之后我们就可以使用这个函数

JAVA JNI操作

在这里我们就可以直接使用这个函数了 使用完函数记得释放句柄

FreeLibrary(hInstLibrary);

然后写完之后我们测试这个JNI函数.生成JniDLL.dll

然后通过JNI调用

JAVA JNI操作

这里我们直接调用

JAVA JNI操作

调用成功

 

 

杨慕义     写

20170304

相关文章: