免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2744 | 回复: 0
打印 上一主题 下一主题

主题:JAVA(JNI,Jnative,JNA)分别调用delphi的动态链接库(dll)的技术交流 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-03 08:32 |只看该作者 |倒序浏览
刚进公司不久就接到了一个很棘手的项目,里面用到的技术以前都没怎么接触过,通过一个多月的努力终于有所收获,但是至今为止还有一点问题没能解决的了,今天晚上我就把这一个多月的折腾分享给大家,希望大家讨论.
  首先我介绍一下本项目所要解决的技术问题:项目是要求用JAVA来调用delphi提供的动态链接库,而且硬件厂商已经提供了库以及接口文档.由于以前没有接触过这样的问题,所以考虑到要跟硬件设备打交道,首先通过查相关的资料,得出在JAVA里面用JNI可以直接访问C提供的动态链接库.但是问题是库是用delphi生成的,貌似用JNI不能直接访问,所以只能用C封装delphi的库供JNI访问,但是这样很麻烦,而且双层封装不稳定,最后在网上看到有人用Jnative可以直接访问delphi的dll库,所以就转向Jnative,但是通过折腾里面还是从在了很多问题,最后通过JavaEye问答讨论,用JNA比用Jnative好用一点,所以最终还是用JNA解决了所需要的问题.下面我就把所需的原码贴出来希望大家指点并讨论.
  1)下面是硬件厂商提供的dll接口文档(为了说明问题我只提供了几个接口的文档):
一、调用参数说明
本动态库中所有函数均需要一个指向下列结构的指针作为参数,这个结构包含了函数运行时所需要的数据。()
Java代码

  • //下面是delphi接口函数所需要的结构体   
  • TParaBuf=record   
  •    ComNo:integer;        //串口号   
  •    Baud:integer;         //波特率 (一般设为115200)   
  •    Sys_Sec:array [1..3] of integer;   //系统扇区1,2,3 (一般设为0,1,2)   
  •    User_Sec:array [1..3] of integer;   //用户扇区1,2,3 (一般设为3,4,5,可以自由设置)   
  •    AuthorNo:array [1..6] of PChar;     //授权码1,2,3,4,5,6 (该授权码由授权卡内的授权码计算得到。)   
  • end;   
  • TPParaBuf=^TParaBuf;   //指向以上结构的指针。   //下面是delphi接口函数所需要的结构体
      TParaBuf=record
        ComNo:integer;        //串口号
        Baud:integer;         //波特率 (一般设为115200)
        Sys_Sec:array [1..3] of integer;   //系统扇区1,2,3 (一般设为0,1,2)
        User_Sec:array [1..3] of integer;   //用户扇区1,2,3 (一般设为3,4,5,可以自由设置)
        AuthorNo:array [1..6] of PChar;     //授权码1,2,3,4,5,6 (该授权码由授权卡内的授权码计算得到。)
      end;
      TPParaBuf=^TParaBuf;        //指向以上结构的指针。
    二、函数说明
    Java代码

  • ReadAuthorInfo   
  • 读取授权卡上的客户编号和客户名称。   
  •   function ReadAuthorInfo(   
  •    buf:TPParaBuf;   
  •    pCustNo,pCustName:PChar):integer;   
  •   
  •     参数   
  •     buf   
  •         指向参数内存块的指针。   
  •     pCustNo   
  •         用于返回客户编号。客户编号固定为4字节,所以调用前必须先开辟足够的空间。   
  •     pCustName   
  •         用于返回客户名称。客户名称固定为14字节,所以调用前必须先开辟足够的空间。   
  •   
  •     返回值   
  •         如果函数调用成功,返回值为0。   
  • 如果函数调用失败,返回值不为0。如需得到错误描述,请调用GetErrMsg。  ReadAuthorInfo
    读取授权卡上的客户编号和客户名称。
      function ReadAuthorInfo(
       buf:TPParaBuf;
       pCustNo,pCustName:PChar):integer;
            参数
            buf
                    指向参数内存块的指针。       
            pCustNo
                    用于返回客户编号。客户编号固定为4字节,所以调用前必须先开辟足够的空间。
            pCustName
                    用于返回客户名称。客户名称固定为14字节,所以调用前必须先开辟足够的空间。
            返回值
                    如果函数调用成功,返回值为0。
    如果函数调用失败,返回值不为0。如需得到错误描述,请调用GetErrMsg。
    Java代码

  • ReadAuthorCard   
  • 读取授权卡上的授权码。   
  •   function ReadAuthorCard(   
  • buf:TPParaBuf):integer;   
  •   
  •     参数   
  •     buf   
  •         指向参数内存块的指针。   
  •   
  •     返回值   
  •         如果函数调用成功,返回值为0。   
  • 如果函数调用失败,返回值不为0。如需得到错误描述,请调用GetErrMsg。   
  • 说明   
  • 调用本函数可以获取授权码,该码保存于参数块中,供其它函数调用。   
  •   
  • Authorize   
  • 对新卡进行授权操作。   
  •   function Authorize(   
  • buf:TPParaBuf):integer;   
  •   
  •     参数   
  •     buf   
  •         指向参数内存块的指针。   
  •   
  •     返回值   
  •         如果函数调用成功,返回值为0。   
  • 如果函数调用失败,返回值不为0。如需得到错误描述,请调用GetErrMsg。  ReadAuthorCard
    读取授权卡上的授权码。
      function ReadAuthorCard(
    buf:TPParaBuf):integer;
            参数
            buf
                    指向参数内存块的指针。
            返回值
                    如果函数调用成功,返回值为0。
    如果函数调用失败,返回值不为0。如需得到错误描述,请调用GetErrMsg。
    说明
    调用本函数可以获取授权码,该码保存于参数块中,供其它函数调用。
    Authorize
    对新卡进行授权操作。
      function Authorize(
    buf:TPParaBuf):integer;
            参数
            buf
                    指向参数内存块的指针。
            返回值
                    如果函数调用成功,返回值为0。
    如果函数调用失败,返回值不为0。如需得到错误描述,请调用GetErrMsg。
       三.
       1)以上的每个函数的参数都要指向delphi提供的一个结构体,但是怎样用JNA来模仿delphi里面的结构体呢,具体如下:
    Java代码

  •   public class ParaBuf  extends Structure{   
  •     public int comNo;   
  •     public int  baud;   
  •     public int[] sysSec = null;   
  •     public int[] userSec = null;   
  •     public ByteByReference[] authorNo = new ByteByReference[6];   
  • }    public class ParaBuf  extends Structure{
            public int comNo;
            public int  baud;
            public int[] sysSec = null;
            public int[] userSec = null;
            public ByteByReference[] authorNo = new ByteByReference[6];
    }
    delphi结构体里面 的成员变量:
    Java代码

  • AuthorNo:array [1..6] of PChar;  AuthorNo:array [1..6] of PChar;可以理解为一个指针数组,但是用JAVA的byte[]是不能替代PChar类型的数组,通过摸索用ByteByReference定义的数组可以跟delphi里面的PChar型数组对应.
    本结构体类必须要继承JNA开源包的Structure抽象类!
    2)定义跟动态链接库的结构函数(我把访问接口函数封装在里一个接口里面)如下:
    Java代码

  • public interface PCSCard extends StdCallLibrary {   
  •         //这句是利用Native.loadLibrary加载所要访问的动态链接库   
  •     PCSCard INSTANCE = (PCSCard)Native.loadLibrary("pcsCardDll", PCSCard.class);//, DEFAULT_OPTIONS);   
  •         //下面三个函数为库的接口函数,其中ParaBuf paraBuf,表示为一个结构体参数   
  •     int ReadAuthorInfo(ParaBuf paraBuf, byte[] customerNo,byte[] customerName);//(读取授权卡上的客户编号和客户名称。)   
  •     int ReadAuthorCard(ParaBuf paraBuf);//(读取授权卡上的授权码。)   
  •     int Authorize(ParaBuf paraBuf);//(对新卡进行授权操作。)      
  • }  public interface PCSCard extends StdCallLibrary {
            //这句是利用Native.loadLibrary加载所要访问的动态链接库
            PCSCard INSTANCE = (PCSCard)Native.loadLibrary("pcsCardDll", PCSCard.class);//, DEFAULT_OPTIONS);
            //下面三个函数为库的接口函数,其中ParaBuf paraBuf,表示为一个结构体参数
            int ReadAuthorInfo(ParaBuf paraBuf, byte[] customerNo,byte[] customerName);//(读取授权卡上的客户编号和客户名称。)
            int ReadAuthorCard(ParaBuf paraBuf);//(读取授权卡上的授权码。)
            int Authorize(ParaBuf paraBuf);//(对新卡进行授权操作。)       
    }
    3)定义访问2)中所定义的接口函数:
    Java代码

  •   public class PCSCardDemo {   
  •       
  •     /**
  •      * 得到一个调用dll函数的INSTANCE:
  •      * @return
  •      */  
  •     public PCSCard getpCSCardInstance(){   
  •         PCSCard lib=PCSCard.INSTANCE;   
  •         return lib;   
  •     }   
  •     /**
  •      * 设置系统结构体指针参数:
  •      * @return 结构体指针对象:
  •      */  
  •     public ParaBuf setParaBuf(){   
  •         ParaBuf paraBuf=new ParaBuf();   
  •         paraBuf.comNo=1;   
  •         paraBuf.baud=115200;   
  •         paraBuf.sysSec=new int[3];   
  •         paraBuf.sysSec[0]=0;   
  •         paraBuf.sysSec[1]=1;   
  •         paraBuf.sysSec[2]=2;   
  •         paraBuf.userSec=new int[3];   
  •         paraBuf.userSec[0]=3;   
  •         paraBuf.userSec[1]=4;   
  •         paraBuf.userSec[2]=5;   
  •         return paraBuf;   
  •     }   
  •     /**
  •      * 读取授权卡上的授权码:
  •      * @param lib
  •      * @param paraBuf
  •      * @return
  •      */  
  •    public ParaBuf readAuthorCard(PCSCard lib,ParaBuf paraBuf){   
  •         int authorCard = lib.ReadAuthorCard(paraBuf);   
  •     System.out.println("return authorCard:" + authorCard);   
  •     ByteByReference[] by = paraBuf.authorNo;   
  •     for(int i=0;i3;i++){   
  •         System.out.println(paraBuf.sysSec);   
  •     }   
  •     for(int i=0;i3;i++){   
  •         System.out.println(paraBuf.userSec);   
  •     }   
  •     for(ByteByReference c : by) {   
  •         if(0 != c.getValue()) {   
  •             System.out.println(c.getValue());   
  •         }   
  •     }   
  •     getErrMsg(lib,authorCard);   
  •     return paraBuf;   
  •    }   
  •       
  •     /**
  •      * 对新卡进行授权操作:
  •      */  
  •     public int authorize(PCSCard lib,ParaBuf paraBuf){   
  •        int returnl =  lib.Authorize(paraBuf);   
  • //函数getErrMsg为调用返回错误信息的函数   
  •        getErrMsg(lib,returnl);   
  •         return returnl;   
  •            
  •     }   
  •     /**
  •      * 得到错误信息:
  •      * @param lib
  •      * @param msgNo
  •      * @return
  •      */  
  •    public String getErrMsg(PCSCard lib,int msgNo){   
  •         byte[] msg = new byte[14];   
  •         boolean bResult=lib.GetErrMsg(msgNo, msg);   
  •         System.out.println("Return:\t" + bResult);   
  •         System.out.println("error message:\t" + new String(msg));   
  •         return new String(msg);   
  •    }   
  •     public static void main(String[] args) throws UnsupportedEncodingException {   
  •         /*
  •          * 初始化:
  •          */  
  •         PCSCardDemo pcscard = new PCSCardDemo();   
  •         PCSCard lib=pcscard.getpCSCardInstance();               //对结构体进行初始化   
  •         ParaBuf paraBuf=pcscard.setParaBuf();   
  •   
  •     /**
  •     * 读取授权卡上的授权码:
  •     */  
  • //pcscard.readAuthorCard(lib, paraBuf);   
  • //System.out.println("authorNo:\t");   
  •         /*
  •          * 读取授权卡信息:
  •          */  
  • //int read = pcscard.readAuthorInfo(lib, paraBuf);   
  •     /**
  •      * 对新卡进行授权操作,在授权的时候必须得到授权卡的授权码
  •      */  
  • //pcscard.authorize(lib,pcscard.readAuthorCard(lib, paraBuf));   
  •     }   
  • }    public class PCSCardDemo {
           
            /**
             * 得到一个调用dll函数的INSTANCE:
             * @return
             */
            public PCSCard getpCSCardInstance(){
                    PCSCard lib=PCSCard.INSTANCE;
                    return lib;
            }
            /**
             * 设置系统结构体指针参数:
             * @return 结构体指针对象:
             */
            public ParaBuf setParaBuf(){
                    ParaBuf paraBuf=new ParaBuf();
                    paraBuf.comNo=1;
                    paraBuf.baud=115200;
                    paraBuf.sysSec=new int[3];
                    paraBuf.sysSec[0]=0;
                    paraBuf.sysSec[1]=1;
                    paraBuf.sysSec[2]=2;
                    paraBuf.userSec=new int[3];
                    paraBuf.userSec[0]=3;
                    paraBuf.userSec[1]=4;
                    paraBuf.userSec[2]=5;
                    return paraBuf;
            }
            /**
             * 读取授权卡上的授权码:
             * @param lib
             * @param paraBuf
             * @return
             */
       public ParaBuf readAuthorCard(PCSCard lib,ParaBuf paraBuf){
                    int authorCard = lib.ReadAuthorCard(paraBuf);
            System.out.println("return authorCard:" + authorCard);
            ByteByReference[] by = paraBuf.authorNo;
            for(int i=0;i
    以上就是访问delphi动态链接库的整个过程.
       明天在将用Jnative访问dll库的过程贴出来,希望大家指点哈
    下面附件有jna的包


    • jna.jar
      (777.2 KB)
    • 下载次数: 6


    本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/47207/showart_1849436.html
  • 您需要登录后才可以回帖 登录 | 注册

    本版积分规则 发表回复

      

    北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
    未成年举报专区
    中国互联网协会会员  联系我们:huangweiwei@itpub.net
    感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

    清除 Cookies - ChinaUnix - Archiver - WAP - TOP