JNI的是:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Sky_interface.SkyJavaAPI.OpenDevice([I[BS)I
at Sky_interface.SkyJavaAPI.OpenDevice(Native Method)
at Sky_interface.JavaTest.Open(JavaTest.java:45)
at Sky_interface.JavaTest.main(JavaTest.java:17)
JNA的是:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'OpenDevice': ???????¨?
at com.sun.jna.Function.<init>(Function.java:179)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:344)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:324)
at com.sun.jna.Library$Handler.invoke(Library.java:203)
at $Proxy0.OpenDevice(Unknown Source)
at skyencard.JavaTest.Open(JavaTest.java:47)
at skyencard.JavaTest.main(JavaTest.java:19)
各位大哥,根据你们的经验,判断大概是哪个地方出现问题?
新手求指点!
Exception in thread "main" java.lang.UnsatisfiedLinkError: Sky_interface.SkyJavaAPI.OpenDevice([I[BS)I
at Sky_interface.SkyJavaAPI.OpenDevice(Native Method)
at Sky_interface.JavaTest.Open(JavaTest.java:45)
at Sky_interface.JavaTest.main(JavaTest.java:17)
JNA的是:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'OpenDevice': ???????¨?
at com.sun.jna.Function.<init>(Function.java:179)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:344)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:324)
at com.sun.jna.Library$Handler.invoke(Library.java:203)
at $Proxy0.OpenDevice(Unknown Source)
at skyencard.JavaTest.Open(JavaTest.java:47)
at skyencard.JavaTest.main(JavaTest.java:19)
各位大哥,根据你们的经验,判断大概是哪个地方出现问题?
新手求指点!
方法参数对吗?
你调用的参数形式是:
([I[BS)I
表示:入参是整数数组、字节数组和short,返回类型整型
符合这种参数形式的OpenDevice方法可能在DLL中并不存在。
int SDF_OpenDevice(
HANDLE *phDeviceHandle, /* 设备句柄 */
int sTimeoutSecond=3600, /* 超时时间 */
char *DeviceName=NULL, /* 设备的名称字符串,如 DEV_PCI_100R */
unsigned int instance=0); /* 设备信息集里的设备序号 */这个是.h头文件里面的,是不是参数不对?
public int OpenDevice(int[] devicehandle,int timeoutsecond,byte[] devicename,int instance);.h头文件里面定义的:
int SDF_OpenDevice(
HANDLE *phDeviceHandle, /* 设备句柄 */
int sTimeoutSecond=3600, /* 超时时间 */
char *DeviceName=NULL, /* 设备的名称字符串,如 DEV_PCI_100R */
unsigned int instance=0);
用JNA怎么还错呢?
一个jclass或者jobject的参数,和一个*env虚拟机指针
估计jna也需要这两个参数吧,毕竟这两个参数是C与JAVA交互的核心。
{
SkyEnCard INSTANCE =(SkyEnCard) Native.loadLibrary("SkyEnCard",SkyEnCard.class); public int OpenDevice(int[] deviceHandle,int timeoutsecond,byte[] devicename,int instance);
JNA这样写对吗?测试test类里面的代码:
int [] DeviceHandle=new int[16];
byte[] DeviceName=new byte[16];
int devicehandle=SkyEnCard.INSTANCE.OpenDevice(DeviceHandle, 3600,DeviceName,0);
System.out.println("打开设备句柄值:" + devicehandle);
(JNIEnv * env, jobject cl,jint price);private native int userCost(int price);这两个方法楼主自己对照一下吧,这两个方法就是native映射,java会通过这个native方法去c里面找这个函数,你可以通过javah 命令来生成.h文件,这样保证不会错。记住,方法名也是有规定的,不能乱取。
1、在Java中定义native方法
2、得到.h头文件,
3、用这个头文件,用C编写一个DLL,
4、从该DLL中调用现有的这个Sky_interface DLL
5、用的时候,携带这两个DLL我想这是比较难的,所以建议你继续尝试JNA。
public int SDF_OpenDevice(int[] devicehandle,int timeoutsecond,byte[] devicename,int instance);
我现在已经有了C函数库,DLL在我来之前就编译好的,而且运行了很久。我来负责写java接口,让客户用java也能调用C函数库。那你看我现在需要做什么?
生成的.h头文件内容好少啊:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class skyencard_SkyJavaAPI */#ifndef _Included_skyencard_SkyJavaAPI
#define _Included_skyencard_SkyJavaAPI
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
就这么结束了?
public native int OpenDevice(int[] devicehandle,int timeoutsecond,byte[] devicename,int instance);JNA的话,参照2009年3月版的“程序员”杂志中的沈东良的文章“使用JNA快速调用原生函数”。总的来说,JNA简单些。
不过你有C代码,所以JNI也可以的,请C程序员协助,改改DLL代码就OK了。
我分析了有三种可能:
1.dll里面函数有问题,我是根据文档写的(但是看到生成dll的.h文件里面函数参数不一样,我修改了之后还是这样的问题。而且这个库已经用了好几年了)
2.路径不对(system32和bin目录下都放了)。
3.我用class生成的.h文件有问题。
4.我的java程序有问题。
2、路径对的。你报的错是找不到函数,又不是找不到库。
3、原先你们的DLL不是给JNI用的,不能直接用它
为了让封装的DLL方法名不起变化,好像在C的代码里要加一段什么标记,加什么忘了,几年前做过的了.
JNA这样定义是错误的 如果C里面是定义的int类型 并且是16位的 那么在JAVA里面要定义成short类型 多去看看资料
import com.sun.jna.Native;
public interface BoxSDK<MobileChanelType> extends Library{
public static final int OP_MODE_SYNC=0; /* 同步操作模式 */
public static final int OP_MODE_ASYNC=1; /* 异步操作模式 */
public static final int ASYNC_MODE_TIMEOUT=108*1000; /*异步超时*/
/* 异步操作下的线程同步模式 */
public static final int SYNC_MODE_CALLBACK=0; /* 回调 */
public static final int SYNC_MODE_EVENT=1; /* 事件 */
public static final int SYNC_MODE_MESSAGE=2; /* 消息 */
BoxSDK INSTANCE=(BoxSDK)Native.loadLibrary("MBPCSDK",BoxSDK.class);
/**
*
* Routine Description:
* 读取银行卡信息.
*
* Arguments:
* lineNum
* [IN] 磁道标识,2,3,23.
*
* Buf2
* [IN/OUT] 从磁条磁道2取数据缓冲区,当lineNum等于3时此值可空,此空间由外部调用维护;
*
* Buf2Len
* [IN] Buf2缓冲区长度,当lineNum 等于3时此值无效;
*
* Buf3
* [IN/OUT] 从磁条磁道3取数据缓冲区,当lineNum等于2时此值可空,此空间由外部调用维护;
*
* Buf3Len
* [IN] Buf3缓冲区长度,当lineNum 等于2时此值无效;
*
* pMode
* [IN] 处理模式结构指针.
*
* Return Value:
* 返回码.
*
*/
public int MagCardGetData(int lineNum, byte[] Buf2, int Buf2Len, byte[] Buf3, int Buf3Len, _DeviceOperateMode pMode);
/**
* 写磁道信息
* @param lineNum 磁道标识2,3,23.
* @param Buf2 写磁条2磁道取数据缓冲区,当lineNum等于时此值可空,此空间由外部调用维护;
* @param Buf2Len Buf2缓冲区长度,当lineNum 等于3时此值无效;
* @param Buf3 写3道磁条数据缓冲区,当lineNum等于时此值可空,此空间由外部调用维护;
* @param Buf3Len Buf3缓冲区长度,当lineNum 等于2时此值无效;
* @param pMode 处理模式结构指针.
* @return 返回码(根据errmsgofdrv.h 错误码定义返回)
*/
public int MagCardWriteData(MagCardLineNo lineNum, String Buf2, String Buf2Len, String Buf3, int Buf3Len,_DeviceOperateMode pMode);
/**
*
* Routine Description:
* 取消磁条卡的异步操作.
*
* Arguments:
* void.
*
* Return Value:
* 返回码.
*
*/
public int CancelMagCard();
/**
*
* Routine Description:
* 读取二代证信息.
*
* Arguments:
* IdCardBuf
* [OUT] 二代证信息结构
*
* pMode
* [IN] 处理模式结构指针.
*
* Return Value:
* 返回码.
*
*/
public int IDCardRead(IDCardData IdCardBuf,_DeviceOperateMode pMode);
/**
* Routine Description:
* 取消异步读取IDCard数据.
*
* Arguments:
* pMode
* [IN] 处理模式结构指针.
*
* Return Value:
* 返回码.
*
*/
public int CancelIDCardRead();
/**
*
* Routine Description:
* 测试串口打印.
*
* Arguments:
* Target
* [IN] 打印数据
*
* pMode
* [IN] 处理模式结构指针.
*
* Return Value:
* 返回码.
*
*/
public int SerialPrt_test(String Target, _DeviceOperateMode pMode);
/**
*
* Routine Description:
* 串口打印.
*
* Arguments:
* Target
* [IN] 打印点阵数据
*
* MatrixNum
* [IN] 点阵总数
*
* pMode
* [IN] 处理模式结构指针.
*
* Return Value:
* 返回码.
*
*/
public int SerialPrt(byte []Target, int MatrixNum, _DeviceOperateMode pMode);
/**
*
* Routine Description:
* 取消异步串口打印.
*
* Arguments:
* pMode
* [IN] 处理模式结构指针.
*
* Return Value:
* 返回码.
*
*/
public int CancelSerialPrt();
/**
*
* Routine Description:
* PSAM卡数据交换.
*
* Arguments:
* nIndex
* [IN] 卡座号(1或0)
*
* Buffer
* [IN] 写到IC卡上的数据,此空间由外部调用维护
* [OUT] 从IC卡上取到的数据.
*
* DataLen
* [IN] 写到IC卡上的数据长度
* [OUT] 从IC卡上取到的数据的长度
*
* BufLen
* [IN] 接收IC卡数据的缓冲区长度
*
* Return Value:
* 返回码.
*
*/
public int PSAMExchange(int nIndex, byte[] Buffer, Integer DataLen, int BufLen);
/**
* Routine Description:
* 从密码键盘上读取密码.
*
* Arguments:
* Buffer
* [IN/OUT] 从密码键盘上读取数据的缓冲区,此空间由外部调用维护
*
* BufLen
* [IN] Buffer长度
*
* ReqLen
* [IN] 请求密码长度
*
* CmdNum
* [IN] 密码读取次序,1-请输入密码;2-请再输入一次
*
* pMode
* [IN] 处理模式结构指针.
*
* Return Value:
* 返回码.
*
*/
public int PinGetPwd(byte[] Buffer, int BufLen, int ReqLen, int CmdNum,_DeviceOperateMode pMode);
/**
*
* Routine Description:
* 取消异步读取密码键盘数据.
*
* Arguments:
* Void.
*
* Return Value:
* 返回码.
*
*/
public int CancelPinGetPwd();
/**
*
* Routine Description:
* 并口打印.
*
* Arguments:
* Target
* [IN] 打印数据
*
* MatrixNum
* [IN] 打印数据长度
*
* pMode
* [IN] 处理模式结构指针.
*
* Return Value:
* 返回码.
*
*/
public int ParallelPrt(byte Target, int MatrixNum, _DeviceOperateMode pMode);
/**
*
* 功能:获取USBKey 设备名
* 输入:pMode 操作模式
* 输出:szDev 设备名
* iLen 出入设备名长度
* 返回值:操作成功,返回0,否则返回错误码
*
*/
public int Vender_GetDeviceName(byte[] szDev, int iLen, _DeviceOperateMode pMode );
/**
*
* 功能: 取消异步获取USBKey 设备名。
* 返回: 0:成功;非0,失败
*
*/
public int AsycnCancelUKGetDeviceName();
/**
*
*功能: 获取USBKey 序列号
*输入: szDevName 设备名
* nNameLen 设备名长度
* pMode 操作模式
*输出: szSN 序列号
*返回值:操作成功,返回0,否则返回错误码
*
*/
public int Vender_GetSN(byte[] szDevName,int nNameLen,byte[] szSN, _DeviceOperateMode pMode );
/**
*
* 功能: 取消异步获取USBKey 序列号。
* 返回: 0:成功;非0,失败
*
*/
public int AsycnCancelUKGetSN ();
/**
*
*功能: 获取USBKey 序列号
*输入: Devnamee 设备名
* upin 解锁密钥
* len 解锁密钥长度
* pMode 操作模式
*输出: 无
*返回值:操作成功,返回0,否则返回错误码
*
*/
public int UnlockKey(String DevName,String upin, int len ,_DeviceOperateMode pMode );
/**
* Routine Description:
* 得到SDK中的对应错误信息.
*
* Arguments:
* dwErrorCode
* [IN] 错误码.
*
* szErrMsg
* [OUT] 保存错误信息的缓存,必须包括串结尾符.
*
* dwBufLen
* [IN] 保存错误信息缓存的长度(字节),必须包括串结尾符.
*
* Return Value:
* ERR_NONE, ERR_NOT_CODE, ERR_MEM_NOT_ENOUGH, ERR_PARAM_VALUE.
*
*/
public int GWIGetErrorMessage(int dwErrCode, byte[] szErrMsg, int dwBufLen );
/**
*
* 功能: 取消异步获取USBKey 解锁。
* 返回: 0:成功;非0,失败
*
*/
int AsycnCancelUKUnlockKey();
int ICCardPowerOn (byte[] Buffer, Integer BufLen);
int ICCardPowerOff ();
int ICCardExchange (byte[] Buffer, Integer DataLen,int BufLen );
}
这是我以前做的项目的一些源代码 参考下 头文件找不到了
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;import com.gwi.ebank.jna.BoxSDK;
import com.gwi.ebank.jna.BoxSDKUSBkey;
import com.gwi.ebank.jna.IDCardData;
import com.gwi.ebank.jna._DeviceOperateMode;
import com.gwi.ebank.print.CreateBMPPicture;
import com.gwi.ebank.unlock.RespShieldData;
import com.gwi.ebank.util.DataBase;
import com.gwi.ebank.util.PublicSimulateData;
import com.gwi.ebank.util.PublicStaticVariable;
import com.gwi.ebank.util.PublicUtil;public class BoxSDKServiceImpl implements IBoxSDKService {
Log logger = LogFactory.getLog(BoxSDKServiceImpl.class);
BoxSDK INSTANCE;
public BoxSDKServiceImpl(){
if(PublicStaticVariable.EDITIONTYPE==PublicStaticVariable.SDKFUNCTION||PublicStaticVariable.EDITIONTYPE==PublicStaticVariable.ALLOFFUNCTION){
INSTANCE=BoxSDK.INSTANCE;
}
} public void print() throws IOException {
int i=PublicStaticVariable.printFlag;
if(i==0){
}else{
CreateBMPPicture createBMPPicture=new CreateBMPPicture();
createBMPPicture.createBMP();
}
}
/**
* 刷银行卡
* @param 磁道号
*/
public Map getCardInfo(int lineNum){ /**
* 初始化数组,数组1为本地操作是否成功标示,0为成功,1为失败
* 如果失败,数组2为失败原因
* 如果成功,数组2为2磁道数据,数组3为3磁道数据
*/
int nResult=0;
Map map=new HashMap();
if(PublicStaticVariable.EDITIONTYPE==PublicStaticVariable.SDKFUNCTION||PublicStaticVariable.EDITIONTYPE==PublicStaticVariable.ALLOFFUNCTION){
_DeviceOperateMode pMode = new _DeviceOperateMode();
pMode.dwSync=0;//同步
pMode.dwTimeout=PublicStaticVariable.dwTimeout;
int Buf2Len = 49;
int Buf3Len = 126;
byte[] Buf2 = new byte[49];
byte[] Buf3 = new byte[126];
nResult=INSTANCE.MagCardGetData(lineNum, Buf2, Buf2Len, Buf3, Buf3Len, pMode);
map.put("nResult", nResult);
if(nResult==0){
if(lineNum==PublicStaticVariable.MAGCARD_LINE_2){
String buf2str = PublicUtil.byteToString(Buf2);
logger.debug(buf2str);
map.put("Buf2", buf2str);
}else if(lineNum==PublicStaticVariable.MAGCARD_LINE_3){
String buf3str = PublicUtil.byteToString(Buf3);
logger.debug(buf3str);
map.put("Buf3", buf3str);
}
}else{
int dwErrCode=nResult;
logger.debug("dwErrCode:"+dwErrCode);
byte[] szErrMsg=new byte[1024];
int dwBufLen=1024;
//得到返回值的错误信息
int result=INSTANCE.GWIGetErrorMessage(dwErrCode, szErrMsg,dwBufLen );
if(result==0){
String szErrMsgstr =PublicUtil.byteToString(szErrMsg);
logger.info(PublicStaticVariable.getCardInfoError+szErrMsgstr);
map.put("errMessage", PublicStaticVariable.getCardInfoError+szErrMsgstr);
}else{
map.put("errMessage", PublicStaticVariable.getCardInfoError+result);
logger.info(PublicStaticVariable.getCardInfoError+result);
}
}
}else{
map.put("nResult", nResult);
//测试使用,如果是0,表示使用尾数是990的那张卡,如果是1,使用尾数是5538的卡
logger.debug("selCardNo:"+PublicStaticVariable.selCardNo);
if(PublicStaticVariable.selCardNo==null||PublicStaticVariable.selCardNo.equals("")){
map.put("Buf2", PublicSimulateData.cardTrack990);
map.put("Buf3", PublicSimulateData.cardTrack990);
}else{
if(PublicStaticVariable.selCardNo.equals("0")){
map.put("Buf2", PublicSimulateData.cardTrack990);
map.put("Buf3", PublicSimulateData.cardTrack990);
}else{
map.put("Buf2", PublicSimulateData.cardTrack5538);
map.put("Buf3", PublicSimulateData.cardTrack5538);
}
}
}
if(nResult==0){
PublicStaticVariable.dealFlag++;
PublicStaticVariable.signDealFlag++;
}
return map;
}
/**
* 获取密码
* @param 读取1次还是2次
* @return 数组1为本地操作是否成功标示,0为成功,1为失败
* 如果失败,数组2为失败原因
* 如果成功,数组2为1次密码,数组3为2次密码
*/
public Map getPassword(int cmdNum){
int nResult=0;
int nResult1=0;
int nResult2=0;
Map map=new HashMap();
if(PublicStaticVariable.EDITIONTYPE==PublicStaticVariable.SDKFUNCTION||PublicStaticVariable.EDITIONTYPE==PublicStaticVariable.ALLOFFUNCTION){
_DeviceOperateMode pMode = new _DeviceOperateMode();
pMode.dwSync=0;//同步
pMode.dwTimeout=PublicStaticVariable.dwTimeout;
int BufLen = 6;
int ReqLen=6;
if(cmdNum==1){
byte[] Buffer = new byte[BufLen];
nResult=INSTANCE.PinGetPwd(Buffer,BufLen,ReqLen,1,pMode);
map.put("nResult", nResult);
if(nResult==0){
String bufferstr = new String(PublicUtil.byteToString(Buffer).trim());
map.put("Buffer",bufferstr );
}else{
//得到返回值的错误信息
int dwErrCode=nResult;
byte[] szErrMsg=new byte[1024];
int dwBufLen=1024;
//得到返回值的错误信息
int result=INSTANCE.GWIGetErrorMessage(dwErrCode, szErrMsg,dwBufLen );
if(result==0){
String szErrMsgstr =PublicUtil.byteToString(szErrMsg);
logger.info(PublicStaticVariable.getCardInfoError+szErrMsgstr);
map.put("errMessage", PublicStaticVariable.getPaswordError+szErrMsgstr);
}else{
logger.info(PublicStaticVariable.getCardInfoError+result);
map.put("errMessage", PublicStaticVariable.getPaswordError+result);
}
}
}else if(cmdNum==2){
byte[] Buffer1 = new byte[BufLen];
byte[] Buffer2 = new byte[BufLen];
nResult1=INSTANCE.PinGetPwd(Buffer1,BufLen,ReqLen,1,pMode);
nResult2=INSTANCE.PinGetPwd(Buffer2,BufLen,ReqLen,2,pMode);
if(nResult1==0&&nResult2==0){
map.put("nResult", 0);
String bufferstr1 = new String(PublicUtil.byteToString(Buffer1).trim());
String bufferstr2 = new String(PublicUtil.byteToString(Buffer2).trim());
map.put("Buffer1",bufferstr1 );
map.put("Buffer2",bufferstr2 );
}else{
//得到返回值的错误信息
int dwErrCode1=nResult1;
byte[] szErrMsg1=new byte[1024];
int dwBufLen1=1024;
int dwErrCode2=nResult2;
byte[] szErrMsg2=new byte[1024];
int dwBufLen2=1024;
int result1=1;
int result2=1;
if(nResult1!=0){
map.put("nResult", nResult1);
result1=INSTANCE.GWIGetErrorMessage(dwErrCode1, szErrMsg1,dwBufLen1 );
}
if(nResult2!=0){
map.put("nResult", nResult2);
result2=INSTANCE.GWIGetErrorMessage(dwErrCode2, szErrMsg2,dwBufLen2 );
}
if(result1==0){
String szErrMsgstr1 =PublicUtil.byteToString(szErrMsg1);
logger.info(PublicStaticVariable.getCardInfoError+szErrMsgstr1);
map.put("errMessage", PublicStaticVariable.getPaswordError+szErrMsgstr1);
}else{
logger.info(PublicStaticVariable.getCardInfoError+result1);
map.put("errMessage", PublicStaticVariable.getPaswordError+result1);
}
if(result2==0){
String szErrMsgstr2 =PublicUtil.byteToString(szErrMsg2);
logger.info(PublicStaticVariable.getCardInfoError+szErrMsgstr2);
map.put("errMessage", PublicStaticVariable.getPaswordError+szErrMsgstr2);
}else{
logger.info(PublicStaticVariable.getCardInfoError+result2);
map.put("errMessage", PublicStaticVariable.getPaswordError+result2);
}
}
}
}else{
map.put("nResult", nResult);
if(cmdNum==1){
map.put("Buffer",PublicSimulateData.cardPassword );
}else if(cmdNum==2){
map.put("Buffer1",PublicSimulateData.cardPassword );
map.put("Buffer2",PublicSimulateData.cardPassword );
}
}
if(cmdNum==1){
if(nResult==0){
PublicStaticVariable.dealFlag++;
PublicStaticVariable.signDealFlag++;
}
}else if(cmdNum==2){
if(nResult1==0&&nResult2==0){
PublicStaticVariable.dealFlag++;
PublicStaticVariable.signDealFlag++;
}
}
return map;
}
调用代码
什么意思?
我用JNA使用的时候也出现这异常
但是如果直接用JNI调用都可以取出数据?
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'NET_DVR_SetReconnect': ???????¨?
at com.sun.jna.Function.<init>(Function.java:126)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:219)
at com.sun.jna.Library$Handler.invoke(Library.java:191)
at $Proxy0.NET_DVR_SetReconnect(Unknown Source)
at moitor.main.Moitor.main(Moitor.java:85)