Chinaunix首页 | 论坛 | 博客
  • 博客访问: 619668
  • 博文数量: 98
  • 博客积分: 10010
  • 博客等级: 上将
  • 技术积分: 1528
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-28 16:20
文章分类

全部博文(98)

文章存档

2011年(1)

2010年(11)

2009年(44)

2008年(42)

我的朋友

分类: Java

2009-03-03 08:32:18

刚进公司不久就接到了一个很棘手的项目,里面用到的技术以前都没怎么接触过,通过一个多月的努力终于有所收获,但是至今为止还有一点问题没能解决的了,今天晚上我就把这一个多月的折腾分享给大家,希望大家讨论.
  首先我介绍一下本项目所要解决的技术问题:项目是要求用JAVA来调用delphi提供的动态链接库,而且硬件厂商已经提供了库以及接口文档.由于以前没有接触过这样的问题,所以考虑到要跟硬件设备打交道,首先通过查相关的资料,得出在JAVA里面用JNI可以直接访问C提供的动态链接库.但是问题是库是用delphi生成的,貌似用JNI不能直接访问,所以只能用C封装delphi的库供JNI访问,但是这样很麻烦,而且双层封装不稳定,最后在网上看到有人用Jnative可以直接访问delphi的dll库,所以就转向Jnative,但是通过折腾里面还是从在了很多问题,最后通过JavaEye问答讨论,用JNA比用Jnative好用一点,所以最终还是用JNA解决了所需要的问题.下面我就把所需的原码贴出来希望大家指点并讨论.

  1)下面是硬件厂商提供的dll接口文档(为了说明问题我只提供了几个接口的文档):
一、调用参数说明
本动态库中所有函数均需要一个指向下列结构的指针作为参数,这个结构包含了函数运行时所需要的数据。()
Java代码 复制代码
  1. //下面是delphi接口函数所需要的结构体   
  2.  TParaBuf=record   
  3.    ComNo:integer;        //串口号   
  4.    Baud:integer;         //波特率 (一般设为115200)   
  5.    Sys_Sec:array [1..3] of integer;   //系统扇区1,2,3 (一般设为0,1,2)   
  6.    User_Sec:array [1..3] of integer;   //用户扇区1,2,3 (一般设为3,4,5,可以自由设置)   
  7.    AuthorNo:array [1..6] of PChar;     //授权码1,2,3,4,5,6 (该授权码由授权卡内的授权码计算得到。)   
  8.  end;   
  9.  TPParaBuf=^TParaBuf;   //指向以上结构的指针。  


二、函数说明
Java代码 复制代码
  1. ReadAuthorInfo   
  2. 读取授权卡上的客户编号和客户名称。   
  3.   function ReadAuthorInfo(   
  4.    buf:TPParaBuf;   
  5.    pCustNo,pCustName:PChar):integer;   
  6.   
  7.     参数   
  8.     buf   
  9.         指向参数内存块的指针。    
  10.     pCustNo   
  11.         用于返回客户编号。客户编号固定为4字节,所以调用前必须先开辟足够的空间。   
  12.     pCustName   
  13.         用于返回客户名称。客户名称固定为14字节,所以调用前必须先开辟足够的空间。   
  14.   
  15.     返回值   
  16.         如果函数调用成功,返回值为0。   
  17. 如果函数调用失败,返回值不为0。如需得到错误描述,请调用GetErrMsg。  


Java代码 复制代码
  1. ReadAuthorCard   
  2. 读取授权卡上的授权码。   
  3.   function ReadAuthorCard(   
  4. buf:TPParaBuf):integer;   
  5.   
  6.     参数   
  7.     buf   
  8.         指向参数内存块的指针。   
  9.   
  10.     返回值   
  11.         如果函数调用成功,返回值为0。   
  12. 如果函数调用失败,返回值不为0。如需得到错误描述,请调用GetErrMsg。   
  13. 说明   
  14. 调用本函数可以获取授权码,该码保存于参数块中,供其它函数调用。   
  15.   
  16. Authorize   
  17. 对新卡进行授权操作。   
  18.   function Authorize(   
  19. buf:TPParaBuf):integer;   
  20.   
  21.     参数   
  22.     buf   
  23.         指向参数内存块的指针。   
  24.   
  25.     返回值   
  26.         如果函数调用成功,返回值为0。   
  27. 如果函数调用失败,返回值不为0。如需得到错误描述,请调用GetErrMsg。  

   三.
   1)以上的每个函数的参数都要指向delphi提供的一个结构体,但是怎样用JNA来模仿delphi里面的结构体呢,具体如下:
Java代码 复制代码
  1.   public class ParaBuf  extends Structure{   
  2.     public int comNo;   
  3.     public int  baud;   
  4.     public int[] sysSec = null;   
  5.     public int[] userSec = null;   
  6.     public ByteByReference[] authorNo = new ByteByReference[6];   
  7. }  

delphi结构体里面 的成员变量:
Java代码 复制代码
  1. AuthorNo:array [1..6] of PChar;  
可以理解为一个指针数组,但是用JAVA的byte[]是不能替代PChar类型的数组,通过摸索用ByteByReference定义的数组可以跟delphi里面的PChar型数组对应.
本结构体类必须要继承JNA开源包的Structure抽象类!
2)定义跟动态链接库的结构函数(我把访问接口函数封装在里一个接口里面)如下:
Java代码 复制代码
  1. public interface PCSCard extends StdCallLibrary {   
  2.         //这句是利用Native.loadLibrary加载所要访问的动态链接库   
  3.     PCSCard INSTANCE = (PCSCard)Native.loadLibrary("pcsCardDll", PCSCard.class);//, DEFAULT_OPTIONS);   
  4.         //下面三个函数为库的接口函数,其中ParaBuf paraBuf,表示为一个结构体参数   
  5.     int ReadAuthorInfo(ParaBuf paraBuf, byte[] customerNo,byte[] customerName);//(读取授权卡上的客户编号和客户名称。)   
  6.     int ReadAuthorCard(ParaBuf paraBuf);//(读取授权卡上的授权码。)   
  7.     int Authorize(ParaBuf paraBuf);//(对新卡进行授权操作。)      
  8. }  


3)定义访问2)中所定义的接口函数:
Java代码 复制代码
  1.   public class PCSCardDemo {   
  2.        
  3.     /**  
  4.      * 得到一个调用dll函数的INSTANCE:  
  5.      * @return  
  6.      */  
  7.     public PCSCard getpCSCardInstance(){   
  8.         PCSCard lib=PCSCard.INSTANCE;   
  9.         return lib;   
  10.     }   
  11.     /**  
  12.      * 设置系统结构体指针参数:  
  13.      * @return 结构体指针对象:  
  14.      */  
  15.     public ParaBuf setParaBuf(){   
  16.         ParaBuf paraBuf=new ParaBuf();   
  17.         paraBuf.comNo=1;   
  18.         paraBuf.baud=115200;   
  19.         paraBuf.sysSec=new int[3];   
  20.         paraBuf.sysSec[0]=0;   
  21.         paraBuf.sysSec[1]=1;   
  22.         paraBuf.sysSec[2]=2;   
  23.         paraBuf.userSec=new int[3];   
  24.         paraBuf.userSec[0]=3;   
  25.         paraBuf.userSec[1]=4;   
  26.         paraBuf.userSec[2]=5;   
  27.         return paraBuf;   
  28.     }   
  29.     /**  
  30.      * 读取授权卡上的授权码:  
  31.      * @param lib  
  32.      * @param paraBuf  
  33.      * @return  
  34.      */  
  35.    public ParaBuf readAuthorCard(PCSCard lib,ParaBuf paraBuf){   
  36.         int authorCard = lib.ReadAuthorCard(paraBuf);   
  37.     System.out.println("return authorCard:" + authorCard);   
  38.     ByteByReference[] by = paraBuf.authorNo;   
  39.     for(int i=0;i<3;i++){   
  40.         System.out.println(paraBuf.sysSec[i]);   
  41.     }   
  42.     for(int i=0;i<3;i++){   
  43.         System.out.println(paraBuf.userSec[i]);   
  44.     }   
  45.     for(ByteByReference c : by) {   
  46.         if(0 != c.getValue()) {   
  47.             System.out.println(c.getValue());   
  48.         }   
  49.     }   
  50.     getErrMsg(lib,authorCard);   
  51.     return paraBuf;   
  52.    }   
  53.       
  54.     /**  
  55.      * 对新卡进行授权操作:  
  56.      */  
  57.     public int authorize(PCSCard lib,ParaBuf paraBuf){   
  58.        int returnl =  lib.Authorize(paraBuf);   
  59. //函数getErrMsg为调用返回错误信息的函数   
  60.        getErrMsg(lib,returnl);   
  61.         return returnl;   
  62.            
  63.     }   
  64.     /**  
  65.      * 得到错误信息:  
  66.      * @param lib  
  67.      * @param msgNo  
  68.      * @return  
  69.      */  
  70.    public String getErrMsg(PCSCard lib,int msgNo){   
  71.         byte[] msg = new byte[14];   
  72.         boolean bResult=lib.GetErrMsg(msgNo, msg);   
  73.         System.out.println("Return:\t" + bResult);   
  74.         System.out.println("error message:\t" + new String(msg));   
  75.         return new String(msg);   
  76.    }   
  77.     public static void main(String[] args) throws UnsupportedEncodingException {   
  78.         /*  
  79.          * 初始化:  
  80.          */  
  81.         PCSCardDemo pcscard = new PCSCardDemo();   
  82.         PCSCard lib=pcscard.getpCSCardInstance();               //对结构体进行初始化   
  83.         ParaBuf paraBuf=pcscard.setParaBuf();   
  84.   
  85.     /**  
  86.     * 读取授权卡上的授权码:  
  87.     */  
  88. //pcscard.readAuthorCard(lib, paraBuf);   
  89. //System.out.println("authorNo:\t");   
  90.         /*  
  91.          * 读取授权卡信息:  
  92.          */  
  93. //int read = pcscard.readAuthorInfo(lib, paraBuf);   
  94.     /**  
  95.      * 对新卡进行授权操作,在授权的时候必须得到授权卡的授权码  
  96.      */  
  97. //pcscard.authorize(lib,pcscard.readAuthorCard(lib, paraBuf));   
  98.     }   
  99. }  

以上就是访问delphi动态链接库的整个过程.
   明天在将用Jnative访问dll库的过程贴出来,希望大家指点哈

下面附件有jna的包
  • (777.2 KB)
  • 下载次数: 6
阅读(3341) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~