JNA框架调用dll动态库(给你整得明明白白)
java调用dll动态库的方法,总的有三种:JNI、JNA、JNative。其中JNA调用DLL是最方便的。网上文章一大堆,我就不废话了。
使用JNA框架调用DLL动态库,步骤如下:
一、环境准备
1.导jar包
jar:jar包版本可以选择,不过好像没什么太大影响,5.8.0的也阔以
pom:
<!--动态库调用--><dependency><groupId>com.sun.jna</groupId><artifactId>jna</artifactId><version>3.0.9</version></dependency>
2.准备好你的dll文件
dll文件有32位和64位的,首先搞清楚你的目标dll是多少位的,然后你的JDK版本位数必须和dll文件保持一致,我本地是搞了好几个JDK7、8、9、32位的互相切换。配JDK可以参考下面https://blog.csdn.net/xiongyouqiang/article/details/79352596?spm=1001.2014.3001.5506
还是不明白怎么切换的可以评论或者私信我!
二、API调用
重头戏来了,和数据库连接一样,JNA连接动态库也是一次资源连接。
如果整个过程你只需要调用一次动态库函数,那就可以选择调完释放的api,如果不确定调用次数,就不释放。
1、调完可释放
/*
* 动态库初始化
*/
//DLL_PATH:DLL文件地址
NativeLibrary INSTANCE = NativeLibrary.getInstance(DLL_PATH);
//动态库的一个函数
String NationEcTrans(String strUrl, String InData, Pointer OutData);
//调用函数
String returnCode = ElecCertDll.INSTANCE.getFunction("NationEcTrans").invokeString(new Object[]{strUrl, input, outPut}, false);
//释放动态库连接,也可以不释放,没有太大关系
ElecCertDll.INSTANCE.dispose();
2、调完不释放
/*** @Description: 初始化动态库* SSCardInterfaceProcess.SSCardDll.class是接口类*/
SSCardInterfaceProcess.SSCardDll INSTANCE = (SSCardInterfaceProcess.SSCardDll) Native.loadLibrary(DLL_PATH, SSCardInterfaceProcess.SSCardDll.class);//动态库的一个函数
NativeLong Init(String pUrl, String pUser);
//调用函数
NativeLong initCode = SSCardDll.INSTANCE.Init(pUrl, pUser);
三、各种错误解决
1、java.lang.UnsatisfiedLinkError: Unable to load library 'C:\Windows\System32\NISEC_SKSC.dll
无法加载动态库,有两个原因如下:
a、路径错误,无论是绝对路径还是相对路径,路径没错都是可行的。网上说了很多一定要使用相对路径或者绝对路径,这个我不认同。需要注意的是,debug出来的路径明明是正确的,也有可能报这个错误。可以参考我这个写法,
/*** 项目根路径*/public static String ROOT_PATH;/*** 动态库名称*/public static final String DLL_NAME = "NationECCode.dll";/*** 动态库名称*/public static String DLL_PATH;static {try {//window是\\,linux是/String separator = System.getProperty("os.name").contains("Windows") ? "\\" : "/";//这里我是看到网上有人这么搞,我也是这么搞,才没有问题。原因也不得其解!ROOT_PATH = (ElecCertInterfaceProcess.class.getResource("/").getPath()).replaceAll("%20", " ").substring(1).replace("/", separator);String url = "dll"+separator+"elecCert"+separator+"32"+separator;DLL_PATH = URLDecoder.decode(ROOT_PATH,"utf-8") +url+DLL_NAME;} catch (UnsupportedEncodingException e) {log.error(e.getMessage());}}
b、动态库支持的jdk版本和你环境的jdk版本不一致。
这个没办法,要么你jdk换掉,要么叫提供动态库的人给你另外搞个版本。
2、乱码问题
无非就是dll和本地环境编码不一致的。
jna默认的编码方式是utf-8,所以需要对应的做修改。
如果dll编码格式是GBK的
在代码的开头设置编码格式就好了
System.setProperty("jna.encoding", "GBK");
3、动态库接口函数,方法参数定义有误
我的动态库是C++写的,有个函数回参是long类型的,我用java的long去接受,直接就报错了。后来看了C和java类型的对照,原来C的long需要java用NativeLong来接收。下面是C、C++和java的对照关系
C++ | Java |
---|---|
char * | String |
word | short |
byte | byte |
byte[] | byte[] |
dword | int |
long | NativeLong |
Void * | Pointer |
lpvoid | Pointer |
lpDword | IntByReference |
HWND | HWND |
char[] | byte[] |
byte * | Pointer |
JAVA | C |
---|---|
Java | 类型 C类型原生表现 |
boolean | int 32位整数(可定制) |
byte | char 8位整数 |
char | wchar_t 平台依赖 |
short | short 16位整数 |
int | int 32位整数 |
long | long,__int64 64位整数 |
float | float 32位浮点数 |
double | double 64位浮点数 |
Buffer/Pointer | pointer 平台依赖(32或64位指针) |
pointer/array | 32或64位指针(参数/返回值)邻接内存(结构体成员) |
String char* | /0结束的数组(nativeencodingorjna.encoding) |
WString | wchar_t* /0结束的数组(unicode) |
String[] | char** /0结束的数组的数组 |
WString[] | wchar_t** /0结束的宽字符数组的数组 |
Structure | struct*/struct 指向结构体的指针(参数或返回值)(或者明确指定是结构体指针)结构体(结构体的成员)(或者明确指定是结构体) |
Union | union 等同于结构体 |
Structure[] | struct[] 结构体的数组,邻接内存 |
Callback | (*fp)() Java函数指针或原生函数指针 |
NativeMapped | varies 依赖于定义 |
NativeLong | long 平台依赖(32或64位整数) |
PointerType | pointer 和Pointer相同 |
另外char*也可以用内存来接收
com.sun.jna.Memory
com.sun.jna.Poniter
Pointer outPut = new Memory(1024 * 10);
String outPutJsonStr = outPut.getString(0);
4、Invalid memory access
这个错误基本可以理解为内存溢出,但是并不是java这边内存溢出了,而是dll那边因为某种原因返回了这样的一个错误。很多同学说是,动态库函数的参数类型定义错误或者长度定义错误,会报这个错误,但是我另一个函数就函数名不一样,其他都一样。由于自己才疏学浅,不懂C\C++。所以错误的根本原因一直没有找到。困扰了我近一周的时间,因为之前的调动态库的容器是JRE,后面改成JDK之后就没这个问题了。估计是某些dll函数依赖了JDK的一些编译环境吧???!!!
新的解决办法,给读卡器换个USB接口就好了,离谱!!!
JNA框架调用dll动态库(给你整得明明白白)相关推荐
- Node.js 调用 dll动态库 以华旭身份证阅读器为例
需求来源 由于使用Electron使用开发桌面端,同时也需要连接硬件设备,单纯使用js方法无法完成,需要通过Node调用dll动态库方式完成. 版本说明: node v12.18.3 (32位) np ...
- Windows系统下通过JNI调用dll动态库的实现
目的:java代码使用jni获取数据 工具: eclipse + Microsoft visual studio (c++) 业务代码: Java代码业务实现: package com.weip.jn ...
- java 动态库_java调用dll动态库文件的一般总结
前一段时间,在项目需求中,需要调用一下第三方的动态库文件,下面是本人一些尝试的经历. 首先需要明白的是,在java中是不能直接调用动态库文件的,因为动态库文件是使用c或是c++编写的,作为一种跨 ...
- java中调用 dll 动态库的简洁方法 JNative
Java中调用DLL方法,是通过JNI接口实现的,http://www.ibm.com/developerworks/cn/java/l-linux-jni/ 这里有详细的说明.大概是先用Java写一 ...
- C++中.lib静态库、.dll动态库的生成及调用2
关于动.静态库的介绍及静态库的生成及调用参见:C++中.lib静态库..dll动态库的生成及调用<1>,本文主要介绍基于VS2015平台的动态库dll的生成及调用方法. 一.动态库的生成 ...
- C++中.lib静态库、.dll动态库的生成及调用1
一.前言 1.动态链接库(dll)与静态链接库(lib): 动态链接库(dll)是一个可以被其他应用程序共享的程序模块,其中封装了一些可以被共享的例程和资源.在链接步骤中,连接器将从库文件取得所需的代 ...
- C# : 调用C++动态库(dll)
在实际软件开发过程中,由于公司使用了多种语言开发,在C#中可能需要实现某个功能,而该功能可能用其他语言已经实现了,那么我们可以调用其他语言写好的模块吗?还有就是,由于C#开发好的项目,我们可以利用re ...
- python调用.net动态库
# python调用.net动态库 ### pythonnet简介 ----------------------------- - pythonnet是cpython的扩展 - pythonnet提供 ...
- C#总结(四)调用C++动态库
由于公司很多底层的SDK,都是C++开发,上层的应用软件却是C# Winform程序.在实际工作的过程中,就经常碰到了C# 程序调用C++ 动态库的问题.最近一直在和C++ 打交道,C# 怎么调用C+ ...
最新文章
- 关于tomcat出现闪退问题
- flash绘制荷花多个图层_Flash鼠绘入门第八课:绘制脱俗荷花
- Hive的10种常用优化总结,再也不怕MapReduce分配不均了
- 化敌为友,微软出手优化 Chrome!
- 逼急了自己人都坑,腾讯内部上演吃鸡大战
- 2.6 利用FTP上传所有文件
- (转)Rust :文件分层
- Java常用集合类详解
- JDK11的下载安装以及环境配置
- EXCEL转PDF后如何居中
- 小哥哥教你100%安装Win10专业版永久激活版(全网独一无二)
- 怎么算特征值和特征矩阵?
- TikTok二面:“聊聊二维码扫码登录的原理”
- HDU 6405 Make ZYB Happy 后缀自动机 前缀和优化
- 京东2022双11预售期,商家该做些什么?
- c语言做图书销售管理系统,C语言图书销售管理系统(38页)-原创力文档
- 使用 Entrust 扩展包在 Laravel 5 中实现 RBAC 权限管理与安装配置
- 汉化+破解Substance Painter 2019 macv2019.1.0图文展示
- 传统 以太网 时隙(slot time) 理解
- linux服务器的完整部署内容详细
热门文章
- 严重性 代码 说明 项目 文件 行 禁止显示状态错误 MSB4030 “是(/ZW)”对于“CL”任务的“CompileAsWinRT”参数是无效值。“CompileAsWinRT”参数的类型为“S
- 智能门锁:NFC刷卡
- (附源码)计算机毕业设计ssm电影院购票系统
- Eclipse svn报错 : org.tigris subversion javahl.ClientException: Working copy not locked;this is proba
- 错误:403 forbidden
- ubuntu nfs 服务器搭建
- python有什么含金量高的证书排行_光环大数据分享18张含金量最高的大数据证书...
- 星淘惠跨境:2023还能做跨境电商吗,跨境电商现状及前景分析
- linux下配置高速缓存dns
- 四款画风清奇的减压小工具,资深职场员工的推荐,还不快收藏