Java与DLL

2019-11-28  本文已影响0人  哥哥是头熊

方案综述

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

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数组区别:

用以下代码创建数组错误

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]
上一篇 下一篇

猜你喜欢

热点阅读