文档库 最新最全的文档下载
当前位置:文档库 › JAVA调用DLL动态链接库

JAVA调用DLL动态链接库

JAVA调用DLL动态链接库
JAVA调用DLL动态链接库

JAVA调用SDK动态链接库

一、案例简述

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

二、案例分析和解决过程

初始化DLL动态库

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

public interface HCNetSDK extends StdCallLibrary {

public static final String path =

"C:\\Tools\\HCNetSDK_v4.1.5.61_20151015_WIN64\\lib\\HCNetSDK";

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[] {"struDeviceV30", "bySupportLock",

"byRetryLoginTime", "byPasswordLevel",

"byRes1", "dwSurplusLockTime", "byRes2"});

}

}

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

声明DLL动态库中方法

DLL动态库方法中有变量和指针的区别,JA V A中没有指针变量,在定义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 = https://www.wendangku.net/doc/0d11196854.html,_DVR_GetStreamKey(lUserId, v30);

if (!getDVRConfigSuc) {

int ret = https://www.wendangku.net/doc/0d11196854.html,_DVR_GetLastError();

String errorMsg = https://www.wendangku.net/doc/0d11196854.html,_DVR_GetErrorMsg(null);

log.error("获取DVR设备AES码流密码调用SDK时出现错误,错误代码:{},描述:{}", ret, errorMsg);

result.setSuccess(false);

result.setErrorMsg("获取DVR设备AES码流密码调用SDK时出现错误,错误代码:"+ret);

}

v30.read();

//解析v30对象返回信息

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

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

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

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

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

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

JA V A跨平台调用DLL动态库方法调用JNative

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

JA V A调用DLL动态库(JNI)

JA V A调用动态链接库DLL之JNative学习

相关文档