gprs dtu 网站首页   gprs dtu 加入收藏   gprs dtu 联系我们   
服务热线:021-64325603    
产品知识
您现在的位置在:首页 > 新闻中心 > 产品知识
亲测JAVA调用DLL及回调函数
时间:2015-08-14 14:28:58  点击:5521

亲测JAVA调用DLL及回调函数

文章来源:正伟数字www.zwtech.com.cn

JAVA调用DLL简直让人伤透脑筋,JAVA提供的JNI要求修改DLL,基本不具可用性。其他的接口方式语焉不详,摸索了很长时间,才找到了真正可用的方式,并实现了由DLL内的函数回调自己的函数。

这次DLL调用亲测了好几种调用DLL的方式,有:JNI、JAwin、Jnative、Jcoba、Jna,最开始看参数类型支持,看网络上的评论,然后看回调函数,特别是回调函数,我所有功能都实现了,最后发现回调不行,只有换接口方式,后来参考项目中DLL厂家提供的DEMO,选定JNA,实现所有功能。支持Pointer、REF、*char、**byte等参数类型,非常好用。

要点说明如下,希望能让你少耽误时间。

下载JNA

在这里下载:

https://jna.dev.java.net/servlets/ProjectDocumentList?folderID=7408&expandFolder=7408&folderID=0

下载后JAR包直接放LIB文件所在文件夹即可。

要测试的DLL使用我们项目中用到的GPRS DLL,代码片段在项目中采用,绝对可用。DLL是上海正伟配套其GPRS产品的,实际使用的DLL,我不能修改他的接口的,DLL名字是“zwgprsnw.dll”,放在项目的文件夹里。

编写接口定义

首先定义一个类Czwgprs,类中定义和DLL匹配的接口,接口中定义和DLL中函数名一致,输入、输出参数对应的函数。

import com.sun.jna.Native;

import com.sun.jna.Pointer;

import com.sun.jna.ptr.PointerByReference;

import com.sun.jna.win32.StdCallLibrary;

public class Czwgprs {

public interface Izwlib extends StdCallLibrary {

boolean zwstartserver(String svrip,int svrpt);

}

加载DLL

public boolean zwloadgprs(){

try{

zwlib = (Izwlib) Native.loadLibrary("zwgprsnw.dll", Izwlib.class);

if ( zwlib !=null ) return true;

} catch (Exception e) {

e.printStackTrace();

}

return false;

}

DLL名字是“zwgprsnw.dll”,放在项目的文件夹里。

简单调用

先调用DLL中“zwstartserver”这个函数,启动GPRS服务器。函数在C#中定义:

bool zwstartserver(string listenip , int listenipport);

在VC中定义:

bool zwstartserver(char * listenip , int listenipport);

把该函数定义到interface Izwlib接口中,String和int类型没有变化,直接定义:

boolean zwstartserver(String svrip,int svrpt);

这样在程序中就可以直接使用了。

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

// TODO add your handling code here:

String svrip = jTextField1.getText();

int svrpt = Integer.parseInt(jTextField2.getText());

try {

boolean zwret = zwgprs.zwlib.zwstartserver(svrip, svrpt);

} catch (Exception e) {

e.printStackTrace();

}

}

点击按钮,试一下,DLL简单功能就实现了。

实现回调

“zwgprsnw.dll”DLL是实现TCP数据接收的,收到TCP数据后,主动调用JAVA的函数,将收到的数据传递给JAVA程序,这是一个难点,怎么实现?

首先,定义回调接口:

public interface izwsvrrevdat extends StdCallCallback {

boolean zwgetdat( PointerByReference zdid, Pointer dat,int datlen) ;

}

定义接口实现:

public class zwimsvrrevdat implements izwsvrrevdat{

public boolean zwgetdat( PointerByReference zdid, Pointer dat,int datlen){

Pointer p = zdid.getValue();

String locip = p.getString(0, false);

locip =locip.trim();

byte[] revdat=dat.getByteArray(0, datlen);

zwui.zwdealzdrev(locip,revdat,datlen);

return true;

}

}

注意看,JNA对指针的支持非常完善。

调用DLL的设置函数,设置回调函数的地址:

public static Izwlib.izwsvrrevdat zwrevdatfunc = new Izwlib.zwimsvrrevdat();

boolean zwsetsvrrevfunc(izwsvrrevdat zwrevdatfunc);

至此,回调函数就实现了,非常简单。JNA真是非常棒!

对比下DLL中函数的C#定义:

回调函数:bool typzwsvrapprev(ref string telid, byte* revdat, int revlen);

设置函数:bool zwsetclntrevfunc(typzwclntapprev func);

程序运行

程序运行后界面如图,可以自动接收TCP数据了。


要特别说明,上面的代码片段来自上海正伟的GPRSCDMA DLL测试代码,他们提供DLL的同时提供了JAVA的完整调用代码,实际使用其实不用自己写了,但是这种技术还是值得学习。

另外,如果需要DLL或者调用代码,也可以和上海正伟联系的,www.zwtech.com.cn 是他们网站。那个JNA包也附带提供的。