JAVA调用DLL动态链接库 下载本文

内容发布更新时间 : 2024/10/16 20:22:25星期一 下面是文章的全部内容请认真阅读。

JAVA调用SDK动态链接库

一、 案例简述

JAVA作为跨平台语言,开发中难免遇到跨平台调用接口方法,近期在项目定制开发过程中,现场需要JAVA平台通过DLL动态链接库设置DVR设备功能,如设置获取DVR设备白名单功能、开启关闭白名单功能、获取设置DVR设备码流是否加密、设置获取DVR设备的AES码流加密信息(包括加密密码、加密方式、加密瞬间等信息)等功能。

二、 案例分析和解决过程

初始化DLL动态库 需要通过接口实体初始化DLL动态库,详细定义格式如下:

public interface HCNetSDK extends StdCallLibrary {

public static final String path =

\

HCNetSDK INSTANCE = (HCNetSDK)Native.loadLibrary(path, HCNetSDK.class);

}

其中:path为DLL动态库的路径,定义DLL动态库方法中的对象INSTANCE为DLL动态库初始化的实例

动态库方法的对象定义需要实现Structure,并重写Structure中的getFieldOrder方法,

详细声明如下: public static class LPNET_DVR_DEVICEINFO_V40 extends Structure { public NET_DVR_DEVICEINFO_V30 struDeviceV30; public byte bySupportLock; public byte byRetryLoginTime; public byte byPasswordLevel; public byte byRes1; public int dwSurplusLockTime; public byte[] byRes2 = new byte[256]; @Override protected List getFieldOrder() { return Arrays.asList(new String[] {\\

\ \ } }

其中:变量属性中byte[]对字节长度有严格要求,必须长度一致,否则调用时会出现JDK源代码错误。

声明DLL动态库中方法

DLL动态库方法中有变量和指针的区别,JAVA中没有指针变量,在定义DLL方法的时候指针的定义需要特别注意:

NativeLong NET_DVR_Login_V30(String sDVRIP, short wDVRPort, String sUserName, String sPassword, LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo); NativeLong NET_DVR_Login_V40(LPNET_DVR_USER_LOGIN_INFO lpLoginInfo, LPNET_DVR_DEVICEINFO_V40 lpDeviceInfo); boolean NET_DVR_GetDVRConfig(NativeLong lUserID, int dwCommand, NativeLong lChannel, Pointer lpOutBuffer, int dwOutBufferSize, IntByReference lpBytesReturned);

其中:Pointer lpOutBuffer变量代表指针参数的传入,在传指针的时候要区别变量和指针的区别。

执行方法调用 实例化DLL动态库对象后,直接调用DLL初始化接口中的方法即可: static HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;

NET_DVR_STREAM_ENC_PARA v30 = new NET_DVR_STREAM_ENC_PARA(); boolean getDVRConfigSuc = true; v30.write(); getDVRConfigSuc = hCNetSDK.NET_DVR_GetStreamKey(lUserId, v30); if (!getDVRConfigSuc) { int ret = hCNetSDK.NET_DVR_GetLastError(); String errorMsg = hCNetSDK.NET_DVR_GetErrorMsg(null); log.error(\获取DVR设备AES码流密码调用SDK时出现错误,错误代码:{},描述:{}\ result.setSuccess(false); result.setErrorMsg(\获取DVR设备AES码流密码调用SDK时出现错误,错误代码:\ } v30.read(); //解析v30对象返回信息

其中:byte[]数组转换成String的时候需要多注意,如byte[]数组为ip地址信息,转换成string

时候首先要将每个byte转换成16进制数字,然后再转换成String变量,否则会出现乱码;boolean指针在传入对象时需要通过定制对象的方法传入,否则方法调用时会提示参数回调写入失败。

三、 经验总结、预防措施及建议

通过本案例我们可以认识到,JAVA中初始化DLL动态库并不复杂,只需要通过Native.loadLibrary(path)方法将path指向DLL动态库路径就可以初始化,DLL动态库中定义声明的方法的调用和初始化也不复杂,只需要通过抽象类将方法初始化即可,但DLL方法中涉及到的变量的定义要求非常严格,参数信息稍有不同就会导致方法调用失败,由于JAVA和C++开发语言的不同,对同一个变量的属性定义不同,对接开发时一定要注意,变量的属性类型定义和长度限制。

鉴于JAVA调用DLL动态库时对参数严格性的要求,在开发过程中,我们应仔细查看DLL动态库对接开发文档,注意文档中参数与指针的区别(name和*name),同时方法调用完成后,注意对资源的释放,避免造成资源没有释放,后来的线程全部挂起处于等待状态导致程序崩溃。

四、 从本文可导出的检查项(checklist)*

JAVA跨平台调用 DLL动态库 方法调用 JNative

五、 参考文献、标准、案例

JAVA调用DLL动态库(JNI)

JAVA调用动态链接库DLL之JNative学习