美文网首页
Java与DLL

Java与DLL

作者: 哥哥是头熊 | 来源:发表于2019-11-28 14:49 被阅读0次

    方案综述

    使用Java调用DLL动态链接库的方案通常有:JNI, JNA, Jacob.

    • JNI:JNI的应用方案是基于Java类和本地函数相映射的。其使用DLL的步骤还是相对比较麻烦,不但涉及到Java编程,还涉及到C/C++编程。
    • JNA:JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架。
    • Jacob:Jacob是Java-Com Bridge的缩写,也可以用来调用DLL。其底层也是使用JNI实现,也具有Windows 的平台依赖性。调用相当方便,不用进行C/C++开发,不用对原始DLL进行封装就可以方便使用。

    JNI,JNA,jawin,jacob和Jcom之间的区别是什么,它们的调用效率怎么排名? —— Accelerator的回答 - 知乎

    JNA与JNI简单对比

    JNA使用比JNI简单,但是JNIJNA性能更好

    JNI vs. JNA performance——stackoverflow

    JNA示例:

    使用注意:32位JDK只能调用32位dll,64位JDK只能调用64位dll

    1.引入JNA相关jar包

    image.png

    2.定义结构体

    找到对应C++的头文件


    头文件
    C++结构体1-1

    在头文件中找到使用到的结构体声明


    头文件中的结构体1-1
                                            //=====================================
                                            //  DeviceID information
                                            //=====================================
    typedef struct _DEVICEID01 {
        int     Size ;                      //Size
        int     Version ;                   //Version
        char    MFG[256] ;                  //Manufacturer name
        char    CMD[256] ;                  //Support command type
        char    MDL[256] ;                  //Product name
        char    CLS[256] ;                  //Device type
        int     PrnType ;                   //Printer type
    } DEVICEID01, *LPDEVICEID01 ;
    
    Java结构体1-2
    public static class DEVICEID01 extends Structure {
                
                public int Size;
                public int Version;
                public byte[] MFG = new byte[256];
                public byte[] CMD = new byte[256];
                public byte[] MDL = new byte[256];
                public byte[] CLS = new byte[256];
                public int PrnType;
                
                public static class ByReference extends DEVICEID01 implements
                Structure.ByReference {}
                
                public static class ByValue extends DEVICEID01 implements
                Structure.ByValue {}
                
                @SuppressWarnings({ "rawtypes", "unchecked" })
                @Override
                protected List getFieldOrder() {
                    List a = new ArrayList();
                    a.add("Size");
                    a.add("Version");
                    a.add("MFG");
                    a.add("CMD");
                    a.add("MDL");
                    a.add("CLS");
                    a.add("PrnType");
                    return a;
                }
            }
    

    C++结构体2-1
                                            //=====================================
                                            //  STATUS information
                                            //=====================================
    typedef struct _STATUSVERSION {         //Status information version
        WORD MajorVersion ;                 //Major version
        WORD MinerVersion ;                 //miner version
    }STATUSVERSION, *LPSTATUSVERSION ;
    
    Java结构体2-1
            public static class STATUSVERSION extends Structure {
                public WORD MajorVersion; 
                public WORD MinerVersion; 
                
                public static class ByReference extends STATUSVERSION implements
                Structure.ByReference {}
                
                public static class ByValue extends STATUSVERSION implements
                Structure.ByValue {}
                
                public STATUSVERSION() {
                    super(ALIGN_NONE);
                }
                
                @SuppressWarnings({ "rawtypes", "unchecked" })
                @Override
                protected List getFieldOrder() {
                    List a = new ArrayList();
                    a.add("MajorVersion");
                    a.add("MinerVersion");
                    return a;
                }
                
            }
    

    C++结构体3-1
    typedef struct _CARTRIDGEANDINKINFO {   //Cartridge and ink information
        BYTE CartridgeType ;                //Cartridge name code
        DWORD ColorType ;                   //Cartridge color code
        BYTE InkRest ;                      //Ink rest information
        BYTE InkDimension ;                 //Ink dimension information
    } CARTRIDGEANDINKINFO, *LPCARTRIDGEANDINKINFO ;
    
    Java结构体3-2
            public static class CARTRIDGEANDINKINFO extends Structure {
                public byte CartridgeType; 
                public DWORD ColorType;
                public byte InkRest; 
                public byte InkDimension;
                
                public static class ByReference extends CARTRIDGEANDINKINFO implements
                Structure.ByReference {}
                
                public static class ByValue extends CARTRIDGEANDINKINFO implements
                Structure.ByValue {}
                
                public CARTRIDGEANDINKINFO() {
                    super(ALIGN_NONE);
                }       
                
                @SuppressWarnings({ "rawtypes", "unchecked" })
                @Override
                protected List getFieldOrder() {
                    List a = new ArrayList();
                    a.add("CartridgeType");
                    a.add("ColorType");
                    a.add("InkRest");
                    a.add("InkDimension");
                    return a;
                }
                
            }
    

    C++结构体4-1
    typedef struct  _CUSTOMSTATUS03_IJ{
        DWORD           Size ;                      // this struct size
        STATUSVERSION   Version ;                   // struct version
    
        BYTE            StatusReplyType;            // status reply type
        BYTE            StatusCode ;                // status code
        BYTE            ErrorCode ;                 // error code
        BYTE            WarningCode[16];            // warning code
    
        CARTRIDGEANDINKINFO     CartridgeInk[16];   // Ink Status
        BYTE            InkRemainInfo[3] ;          // ink remain information
    
        DWORD           MonochromePrintedNumber;    // monochrome printed number
        DWORD           ColorPrintedNumber;         // color printed number
    
    } CUSTOMSTATUS03_IJ, *LPCUSTOMSTATUS03_IJ;
    
    Java结构体4-2
            public static class CUSTOMSTATUS03_IJ extends Structure {
                public DWORD Size;
                public STATUSVERSION Version;
                
                public byte StatusReplyType;
                public byte StatusCode;
                public byte ErrorCode;
                public byte[] WarningCode = new byte[16];
                
                public CARTRIDGEANDINKINFO[] CartridgeInk = new CARTRIDGEANDINKINFO[16];
                public byte[] InkRemainInfo = new byte[3];
                
                public DWORD MonochromePrintedNumber;
                public DWORD ColorPrintedNumber;
                
                public static class ByReference extends CUSTOMSTATUS03_IJ implements
                Structure.ByReference {}
                
                public static class ByValue extends CUSTOMSTATUS03_IJ implements
                Structure.ByValue {}
                
                public CUSTOMSTATUS03_IJ() {
                    super(ALIGN_NONE);
                }   
    
                @SuppressWarnings({ "rawtypes", "unchecked" })
                @Override
                protected List getFieldOrder() {
                    List a = new ArrayList();
                    a.add("Size");
                    a.add("Version");
                    a.add("StatusReplyType");
                    a.add("StatusCode");
                    a.add("ErrorCode");
                    a.add("WarningCode");
                    a.add("CartridgeInk");
                    a.add("InkRemainInfo");
                    a.add("MonochromePrintedNumber");
                    a.add("ColorPrintedNumber");
                    return a;
                }           
            }
            
    

    关于数组的处理

    1. Java数组与C数组区别:

    • Java的数组在栈里也许是连续的,但是指向的是堆里面的对象,所以不是连续的内存空间
    • 而C的数组在内存里是连续的内存空间


      Java数组与C数组示意.png

    用以下代码创建数组错误

    CLibrary.OIDINFO[] oidInfo = new CLibrary.OIDINFO[100]; 
    
    CLibrary.OIDINFO.ByReference[] oidInfo = new CLibrary.OIDINFO.ByReference[100]; 
    

    用以下代码创建数组正确

    OIDINFO[] oidInfo = (OIDINFO[])new OIDINFO().toArray(100);
    

    2. 关于byte[ ]

    JNA 中,char * 和 char 类型都可以映射为 byte[] 类型
    通过Java里面String里面的getBytes()方法可以快速将String转换为Byte数组

    但是在JNA里面这样使用会有一定的问题
    原因是C 中的 char 数组是以一个 NULL 字符作为结束中止标识, 使用Java 中的 getBytes() 并不会在byte 数组后加结束符,导致读取参数数组越界,强制结束。

    JNA里面自带了toByteArray方法,使用toByteArray更稳妥。

    以下代码比较了两种方式的区别:

    public static String OID_REBOOT = "1.3.6.1.2.1.43.5.1.1.3.1";
    
    byte[] a = TestEpson.OID_REBOOT.getBytes();
    System.out.println(Arrays.toString(a));
    \\输出[49, 46, 51, 46, 54, 46, 49, 46, 50, 46, 49, 46, 52, 51, 46, 53, 46, 49, 46, 49, 46, 51, 46, 49]    
    
    byte[] b = Native.toByteArray(TestEpson.OID_REBOOT);
    System.out.println(Arrays.toString(b));
    \\输出[49, 46, 51, 46, 54, 46, 49, 46, 50, 46, 49, 46, 52, 51, 46, 53, 46, 49, 46, 49, 46, 51, 46, 49, 0]
    

    相关文章

      网友评论

          本文标题:Java与DLL

          本文链接:https://www.haomeiwen.com/subject/owcbwctx.html