本案例为使用JNA,对接顶尖ACLAS电子秤。配置回调函数后,电子秤称重发生变化,自动回调称重数据。
1.JNA调用DLL方法声明
1.只用指明dll文件所在的文件路径+文件名称,不用带后缀。
2.根据DLL接口类型,一一对应JAVA类型。
/**
* DLL动态库调用方法
*/
public interface IMyDll extends Library {
// DLL文件默认路径为项目根目录,若DLL文件存放在项目外,请使用绝对路径
IMyDll INSTANCE = (IMyDll) Native.load("D://SensorDll", IMyDll.class);
//1.设置参数及回调函数
void __Config(Integer retrycnt, Integer TimeOut, boolean debug,
Pointer ErrorInfo, Callback RecInfo, Pointer opboxInfo, Pointer leadinfo, Callback IS1Info, Pointer PotInfo);
//2.打开设备 (波特率默认是 9600)
Boolean __Open(Object commName, Integer bandRate);
}
2.JNA回调函数声明
public interface IMyCallback extends Callback {
void displayWeightEvent(Double NetWeight, Double Tare, Double Grossweight,
Integer mode, Integer DecimalDigit, Integer UnitChar,
Integer oldAd, Integer FilterAd, Integer ZeroAd, Integer WeightAd, Integer Integer);
}
public interface IMyCallback2 extends Callback {
void displayIs1Info2(String status, String sign, String Weight, String fUnit, Integer flag);
}
public static class MyCallbackImpl implements IMyCallback {
@Override
public void displayWeightEvent(Double NetWeight, Double Tare, Double Grossweight, Integer Mode,
Integer DecimalDigit, Integer UnitChar, Integer OldAd, Integer FilterAd, Integer ZeroAd, Integer WeightAd,
Integer flag) {
// TODO Auto-generated method stub
log.info("1回调成功...NetWeight=" + NetWeight + "mode=" + Mode + "DecimalDigit=" + DecimalDigit + ",UnitChar=" + UnitChar + ",flag=" + flag);
}
}
public static class MyCallbackImpl2 implements IMyCallback2 {
@Override
public void displayIs1Info2(String status, String sign, String Weight, String fUnit, Integer flag) {
// TODO Auto-generated method stub
log.info("2回调成功...status=" + status + ",sign=" + sign + ",weight=" + Weight + ",funit=" + fUnit + ",flag=" + flag);
}
}
3.调用以及回调函数使用
1.直接new MyCallbackImpl() 回调实现类,然后传递给config。
public class Test{
public static void config() {
log.info("config...start...");
MyCallbackImpl myCallback = new MyCallbackImpl();
MyCallbackImpl2 myCallback2 = new MyCallbackImpl2();
IMyDll.INSTANCE.__Config(5, 2000, true, null, myCallback, null,
null, myCallback2, null);
log.info("config...end...");
}
public static Boolean open() {
System.out.println("open...start...");
Boolean result = IMyDll.INSTANCE.__Open("COM2", 9600);
log.info("open...restult = " + result);
return result;
}
public static void main(String[] args) {
config();
open();
}
}
四.重点,存在的问题及改正
在实际使用javaFx作为可视化界面开发中,主线程一直存在。正常情况下,DLL会一直回调到代码中来,可以持续获得回调的数据,但是并没有!每次启动的时候,只会回调一次或几次,之后就没有回调,感觉后面就堵塞了。
其实,是因为设置回调函数的时候,直接new MyCallbackImpl() 回调实现类,然后传递给config,这种操作是错误的。因为JVM会自动回收对象,导致Dll回调的时候找不到。
正确的做法应该改为static声明,让对象持续存活,不至于被GC,这样才能持续回调。
public class MainController {
public static IMyDll.MyCallbackImpl myCallback;
private static IMyDll.MyCallbackImpl2 myCallback2;
public static void config() {
log.info("config...start...");
myCallback = new IMyDll.MyCallbackImpl();
myCallback2 = new IMyDll.MyCallbackImpl2();
IMyDll.INSTANCE.__Config(5, 2000, true, null, myCallback, null,
null, myCallback2, null);
log.info("config...end...");
}
}