【Java Native】【JNI技术的实践(使用VS2010)】
来源:互联网 发布:2018优化重组数学答案 编辑:程序博客网 时间:2024/06/05 23:06
因为现在平台的脚本都从C++迁移到java上来,我们需增加Java对-X读卡器的支持,但是-X读卡器并不是标准的PC/SC设备,里面包含了公司自己的通讯协议。因此我们不能使用现有的开源的jpcsc库来开发,而必须使用Java Native技术来实现软件与-X读卡器的通讯。
现在手里有-X读卡器通讯的dll文件:wdcrwx.dll。虽然说只有要dll文件就可以开发了,但是实际上这样需要做很多函数的声明,使用起来非常麻烦。因此还需要找到对应的lib文件和头文件:wdcrwx.lib、wdcrwx.h。
下面开始正式编码:
1. JAVA端的工作
第1步,在java程序中,首先声明需要在类中所调用的库的名称,如下:
static{
System.loadLibrary("Promotion_crwx");
}
在这里,库的扩展名不用写,究竟使用的是DLL还是SO,由系统判断。
第2步,对Native方法进行声明,如下:
publicnative static int readerOpen(String name);
publicnative static int readerClose(int fd);
publicnative static String cardReset(int fd);
publicnative static byte[] sendCmd(int fd,byte[] Cmd);
publicnative static void setNad(int fd, byte nad);
第3步,编译该java程序,生成CLASS。再用javah命令,生成JNI的头文件。
注意,编译的时候一定要加上路径,要不然会提示找不到类。例如上面的类的类名是:CRWXService,包名是:com.watchdata.framework.cardcomm.crwx。因此需要这样编译:
>javac–d ./ CRWXService.java
>javah –classpath./ com.watchdata.framework.cardcomm.crwx.CRWXService
在当前java文件目录下生成com文件夹下,按包路径深入文件夹可以找到CRWXService.class。同时,在当前java文件目录下也生成了对应的头文件:com_watchdata_framework_cardcomm_crwx_CRWXService.h
到这里,java端的工作完毕,开始C/C++端的工作
2. C/C++端的工作
之前有个jni的工程C/C++端是用VC6.0写的,但是我总觉得没有必要要那么老的IDE吧,虽然经典,但是太丑,又那么不智能,为什么不用visual studio呢。何况小飞他们的java虚拟机的C工程都是用vs2010建的,至少说明vs还是挺好用的吧。
第1步,在vs2010中建立名称为Promotion_crwx的win32控制台应用程序。如下所示:
第2步,下一步,设置应用程序类型:DLL,附加选项:导出符号。如下图所示:
点击完成。
第3步,将 生成的com_watchdata_framework_cardcomm_crwx_CRWXService.h拷贝到工程下,引入该头文件。这时会报“无法识别符号JNIEXPORT”类似的错误,因为他们是jni头文件声明的关键字。我们需要引入jni的库,或者拷贝相应的头文件到工程下引入。我采用的是第2种:拷贝%jdk%\include\win32\jni_md.h和%jdk%\include\jni.h到工程中引入。
将com_watchdata_framework_cardcomm_crwx_CRWXService.h中#include <jni.h>改为#include “jni.h”。编译通过,生成dll文件。但是dll文件中只有示例中的接口,并不是我们想要的接口。下面开始修改。
第4步,删除Promotion_crwx.h和Promotion_crwx.cpp中的所有内容(这些都是示例代码,我们不需要)。然后在stdafx.h中写入:#include “com_watchdata_framework_cardcomm_crwx_CRWXService.h",在Promotion_crwx.cpp中实现该头文件中函数,为了验证我们是否成功调用,我们在每个函数里都加上一段打印字符串。如下图所示:
这个时候重新生成Promotion_crwx.dll文件。通过dll查看器,我们看到生成的接口都以””_java”开头,名称中含有包路径和类名,如下图所示:
第5步,为了验证我们的dll是可以被调用的,我们需要先测试一下。
首先,将dll文件拷贝到java.library.path目录下,或者在运行java时设置java.library.path的路径。如下图所示:
(注意:在在eclipse中运行java代码时,java. library.path指向的是我的lib文件夹;但是将java代码打包或者在控制台单独运行的时候,java. library.path包含了system32目录,所以只要将dll文件拷贝到system32下就可以了。如果不确定java. library.path指向的是哪里,可以用
System.out.println("java. library.path=" +System.getProperty("java.library.path"));
打印出来看看。)
然后在main方法中调用java端的native方法,运行结果中输出了我们期望的字符串说明调用成功。如下图所示:
第6步,如果是普通的jni,我们到此就完成了。但因为我们需要调用其他的dll,因此还需要下面这一步。将wdcrwx.dll、wdcrwx.lib、wdcrwx.h拷贝到工程目录下,引入头文件wdcrwx.h,引入资源文件wdcrwx.dll、wdcrwx.lib。并在stdafx.h中写入:#include "wdcrwx.h"。然后我们就可以在Promotion_crwx.cpp中调用dll中的函数了。下面是实现后的一个截图:
- 【Java Native】【JNI技术的实践(使用VS2010)】
- 使用 Java Native Interface 的最佳实践(JNI)
- JNI(Java Native Interface)的使用
- JNI(Java Native Interface)的使用
- JNI(Java Native Interface)的使用
- JNI技术(Java Native Interface)
- JNI技术(Java Native Interface)
- JNI(Java Native Interface)首次使用
- 使用 Java Native Interface 的最佳实践
- 使用 Java Native Interface 的最佳实践
- 使用 Java Native Interface 的最佳实践
- 使用 Java Native Interface 的最佳实践
- 使用 Java Native Interface 的最佳实践
- 使用 Java Native Interface 的最佳实践
- 使用 Java Native Interface 的最佳实践
- 使用 Java Native Interface 的最佳实践
- 使用 Java Native Interface 的最佳实践
- 使用 Java Native Interface 的最佳实践
- 可任意改变背景颜色的万年历
- JNI学习三:数组访问(1)——简单类型数组
- (转)C++拷贝构造函数(深拷贝,浅拷贝)
- MediaPlayer 的DEMO(temp)
- 兼容火狐、谷歌等主流浏览器的万年历
- 【Java Native】【JNI技术的实践(使用VS2010)】
- [wp7软件]wp7~~相册加密软件~~集合贴~~
- Opencv学习笔记(十)高斯混合模型
- 分布式搜索elasticsearch java API 之(一)------与集群交互
- 简洁,漂亮实用的万年历
- main方法中同时加载多个Spring文件
- 使用Source Insight看.cc文件
- 已知6点,求两平面夹角
- 海量存储系列:分布式存储的场景