最近安装eclipse给一个客户开发项目,项目中用jna调用了自定义的一个本地动态链接库,动态链接库名称是uuwisehelper.dll。该动态链接库的功能是验证码识别功能。
eclipse中调用调试是运行正常的,但是程序打包后报错提示加载动态库失败。
咨询优优云的技术(该动态链接库的技术支持)后获知DLL是C编写的。
于是在谷歌,百度,咨询优优云的动态链接库编译作者。得知C编写的动态链接库配合eclipse和jna的时候可能是C和Java的数据类型不一致,导致类型对应出现问题。
期间尝试了很多网上提供的方法。下面特此总结一下分享给大家:
1.将动态库路径写为绝对路径
2.同时也需要设置jna.library.path 在相应路径中加入动态链接库
3.JDK如果是64位的话,请更换一个32位的JDK重新调试打包一下。
一般做过以上三点之后,重新运行打包后的文件就不会提示加载加载动态库失败了。
特此分享在验证码识别时的样例代码如下:
package com.cqz.dm;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.imageio.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 imageFile) throws Exception
{
BufferedImage img = ImageIO.read(imageFile);
ByteArrayOutputStream buf = new ByteArrayOutputStream((int) imageFile.length());
try
{
ImageIO.write(img, "jpg", buf);
} catch (Exception e)
{
e.printStackTrace();
return null;
}
return buf.toByteArray();
}
public static byte[] toByteArrayFromFile(String imageFile) throws Exception
{
InputStream is = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
try
{
is = new FileInputStream(imageFile);
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:如有错误,望各位海涵。