最近安装eclipse给一个客户开发项目,项目中用jna调用了自定义的一个本地动态链接库,动态链接库名称是uuwisehelper.dll。该动态链接库的功能是验证码识别功能。


eclipse调用调试是运行正常的,但是程序打包后报错提示加载动态库失败。

咨询优优云的技术(该动态链接库的技术支持)后获知DLLC编写的。


于是在谷歌,百度,咨询优优云的动态链接库编译作者。得知C编写的动态链接库配合eclipsejna的时候可能是CJava的数据类型不一致,导致类型对应出现问题。


期间尝试了很多网上提供的方法。下面特此总结一下分享给大家:


1.将动态库路径写为绝对路径


2.同时也需要设置jna.library.path 在相应路径中加入动态链接库


3.JDK如果是64位的话,请更换一个32位的JDK重新调试打包一下。


一般做过以上三点之后,重新运行打包后的文件就不会提示加载加载动态库失败了。


特此分享在验证码识别时的样例代码如下:


package com.cqz.dm;



import java.awt.p_w_picpath.BufferedImage;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.InputStream;


import javax.p_w_picpathio.ImageIO;


import com.sun.jna.Library;

import com.sun.jna.Native;


/**

* 更多函数细节:dll.uuwise.com

*

*/

public class CQZDMDLL

{

public static String USERNAME = "UserName"; //UU用户名

public static String PASSWORD = "PassWord"; //UU密码

public static String DLLPATH = "lib\\UUWiseHelper"; //DLL

public static String IMGPATH = "img\\test.png";

public static int SOFTID = 2097; //软件ID

public static String SOFTKEY = "b7ee76f547e34516bc30f6eb6c67c7db"; //软件KEY


public interface DM extends Library

{

DM INSTANCE = (DM) Native.loadLibrary(DLLPATH, DM.class);

public int uu_reportError(int id);

public int uu_setTimeOut(int nTimeOut);

public void uu_setSoftInfoA(int softId, String softKey);

public int uu_loginA(String UserName, String passWord);

public int uu_getScoreA (String UserName, String passWord);

public int uu_recognizeByCodeTypeAndBytesA (byte[] picContent, int piclen, int codeType, byte[] returnResult);

public void uu_getResultA(int nCodeID,String pCodeResult);

}


public static void main(String[] args) throws Exception

{

int userID;

DM.INSTANCE.uu_setSoftInfoA(SOFTID, SOFTKEY);

userID=DM.INSTANCE.uu_loginA(USERNAME, PASSWORD);

if(userID>0){

System.out.println("userID is:"+userID);

System.out.println("user score is:"+DM.INSTANCE.uu_getScoreA(USERNAME, PASSWORD));


File f = new File(IMGPATH);

byte[] by = toByteArray(f);


byte[] resultBtye=new byte[30]; //为识别结果申请内存空间

int codeID=DM.INSTANCE.uu_recognizeByCodeTypeAndBytesA(by, by.length, 1, resultBtye); //调用识别函数,resultBtye为识别结果

String  resultResult = new String(resultBtye,"UTF-8");

resultResult=resultResult.trim();

System.out.println("this img codeID:"+codeID);

System.out.println("return recongize Result:"+resultResult);


/*

//测试报错 开始,真实环境不可这样用,需要在实际验证码打错的情况下,执行报错函数进行报错,恶意报错会导致封号

System.out.println("报错前 user score is:"+DM.INSTANCE.uu_getScoreA(USERNAME, PASSWORD));

int reportErrorResult;

reportErrorResult=DM.INSTANCE.uu_reportError(codeID);

if(reportErrorResult==0)

{

System.out.println("报错后 user score is:"+DM.INSTANCE.uu_getScoreA(USERNAME, PASSWORD));

}else

{

System.out.println("报错失败,原因未知");

}

//测试报错 开始,真实环境不可这样用,需要在实际验证码打错的情况下,执行报错函数进行报错,恶意报错会导致封号

*/

}else{

System.out.println("登录失败,错误代码为:"+userID); //错误代码请对应dll.uuwise.com各函数值查看

}  

}



public static byte[] toByteArray(File p_w_picpathFile) throws Exception

{

BufferedImage img = ImageIO.read(p_w_picpathFile);

ByteArrayOutputStream buf = new ByteArrayOutputStream((int) p_w_picpathFile.length());

try

{

ImageIO.write(img, "jpg", buf);

} catch (Exception e)

{

e.printStackTrace();

return null;

}

return buf.toByteArray();

}


public static byte[] toByteArrayFromFile(String p_w_picpathFile) throws Exception

{

InputStream is = null;


ByteArrayOutputStream out = new ByteArrayOutputStream();


try

{

is = new FileInputStream(p_w_picpathFile);


byte[] b = new byte[1024];


int n;


while ((n = is.read(b)) != -1)

{


out.write(b, 0, n);


}// end while


} catch (Exception e)

{

throw new Exception("System error,SendTimingMms.getBytesFromFile", e);

} finally

{


if (is != null)

{

try

{

is.close();

} catch (Exception e)

{}// end try

}// end if


}// end try

return out.toByteArray();

}


}


PS:如有错误,望各位海涵。