Java通过JNA调用dll动态库demo并生成相应jar文件详细教程

Java通过JNA调用动态库

  编写一个demo程序,通过导入JNA的jar包使用JNA来进行zpl动态库的调用,完成zpl打印机的打开端口,关闭端口,打印文本,条码以及二维码的功能。

1:下载Jna的jar包并且在项目中导入jar包文件

  通过在mvn仓库下载对应版本的jar包文件,此项目下载的是5.5.0的jar包,之后将jar包放入项目目录中,注意jar包存放的位置非常关键!一开始我只将jar包放置在根目录中,导致后期在项目中调用jna库中的类时出现NOCLASSFOUND异常,困扰了我很长时间,因此在项目中规范存放并导入jar包很重要。
  首先在工程项目的根目录中新建一个lib文件,并将jar包存放在lib文件夹中。
在这里插入图片描述
  将jar包添加到构建路径中。右键使用的jar包,选择选择Build Path–>Add to Build Path。
在这里插入图片描述   此时工程目录下就多了一个referenced libraries目录,在该目录下有刚刚添加的jar包,这样jar包才是真正在项目中添加完毕。
在这里插入图片描述

2:编写接口类

  要想通过JNA调用DLL动态库,那就需要新建一个接口类用来导出DLL动态库的方法。
  首先导入JNA包中的一系列类用来加载dll动态库以及完成java函数与动态库中的c函数方法转换以及对应形参成员的类型映射装换实现,具体的c -> java映射下图所示。
![在这里插入图片描述](https://img-blog.csdnimg.cn/41e50027459f4b929be07faa67a741da.png在这里插入图片描述

  注意上述的java方法都是将dll库中需要使用的函数进行转换映射为相应的java函数方法以便java程序进行方法的调用。如果你只有相应动态库而没有源码无法得知动态库中的方法时可以通过以下方法进行dll动态库中的方法查看。
在这里插入图片描述

  下图是相应的c函数形参数据类型与java形参数据类型的转换表。
在这里插入图片描述

   通过以上实现即可完成dll动态库的调用以及相应dll库函数的转化成java方法实现。

编写Demo程序实现动态库函数的调用

  这就需要通过调用java的控件类来完成gui界面的绘制,具体代码如下所示。通过导入上面的接口类,并调用接口类中的实例成员的方法即可实现函数调用。
在这里插入图片描述
   在实现调用dll动态库函数的时候一定要注意参数装换有没有出现错误,这个一定要非常仔细检查,否则后期在通过java调用的时候会出现很多问题,有些到后期代码量增多的时候或许就不好排查了,因此在参照c ->java 映射表的时候需要仔细查看,还有一些数据类型映射实际还没有讲到,后期有机会会总结一下具体的动态库调用数据类型装换。

具体项目中出现的问题:
    在调用打印函数时打印文本时发现调用成功,但是打印机并没有进行打印,后来发现在打印函数前后需要加上标签函数设置开始以及结束标签后才会开始正常打印。
   在打印文本以及条码时候出现编码格式问题,导致打印出来的数据均是乱码状态,通过检查发现输入的数据类型应该要改成WString,改后可以成功打印。

package PrinterSdk;
import com.sun.jna.WString;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.UnsupportedEncodingException;
import PrinterSdk.DllUse;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import com.sun.jna.ptr.IntByReference;
public class PrinterDemo {
    private JFrame frame;
    private JTextField barcode_data;
    private JTextField qrcode_data;
    private JTextField Text;
    private JButton PrBar_btn;
    private JButton PrQr_btn;
    private JButton PrTx_btn;
    private JButton openPort_btn;
    private JButton closePort_btn;
    
    private  int port;
    
    public PrinterDemo()
    {
        initialize();
    }
    
    private void initialize()
    {
        frame=new JFrame();
        frame.setBounds(100, 100, 700, 550);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);
        frame.setTitle("PrinterDemo");
        
        PrTx_btn=new JButton("打印文本");
        PrTx_btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                try {
//                    IntByReference i=new IntByReference(0);
//                    int o1=DllUse.instanceDll.OpenPortEx(0, i, 9600, 0);
                    WString data = new WString(Text.getText().toString());//.getBytes("gb18030");
//                    int s=DllUse.instanceDll.StartFormat_ZPL(100,100,10000,100);
                    int o=DllUse.instanceDll.StartData_ZPL(2000, 2000);
//                    DllUse.instanceDll.SetDefaultFont_ZPL(o1, "D".getBytes("gb18030"), 9, 5);
//                    DllUse.instanceDll.SetDataFont_ZPL("C".getBytes("gb18030"), 10000, 10000, "N".getBytes("gb18030"));
//                    DllUse.instanceDll.DataOrientation_ZPL("N".getBytes("gb18030"));
                    String data1="no.1234567";
    //                byte[] data2=data1.getBytes("gb18030");
                    int s=DllUse.instanceDll.StartFormat_ZPL(200,200,40039,40039);
                    int i1=DllUse.instanceDll.PrintData_ZPL(data);
                    DllUse.instanceDll.EndFormat_ZPL(port);
                    System.out.println("文本:"+i1+" "+s);
//                    int status=DllUse.instanceDll.GetPrintStatues_USB(0);
//                    System.out.println("打印机状态:"+status);
                } catch (Exception e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        });
        PrTx_btn.setBounds(500, 100, 100, 80);
        frame.getContentPane().add(PrTx_btn);
        
        PrBar_btn=new JButton("打印条码");
        PrBar_btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                try {
//                    IntByReference i1=new IntByReference(0);
//                    int o1=DllUse.instanceDll.OpenPortEx(0, i1, 9600, 0);
                    DllUse.instanceDll.DataOrientation_ZPL("N".getBytes("gb18030"));
                    WString data = new WString(barcode_data.getText().toString());
                    WString data1 = new WString("Y");
//                    byte[] data=barcode_data.getText().getBytes("gb18030");
//                    CodeType type=CodeType.CODE_39;
//                    System.out.println(type);
                    int s1=DllUse.instanceDll.StartFormat_ZPL(200,200,40039,10000);
                    int i=DllUse.instanceDll.BarCode_ZPL(data,2, 100, data1);
                    DllUse.instanceDll.EndFormat_ZPL(port);
                    System.out.println("条码:"+i);
                } catch (UnsupportedEncodingException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                
            }
        });
        PrBar_btn.setBounds(500, 200, 100, 80);
        frame.getContentPane().add(PrBar_btn);
        
        PrQr_btn=new JButton("打印二维码");
        PrQr_btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                try {
//                    IntByReference i1=new IntByReference(0);
//                    int o1=DllUse.instanceDll.OpenPortEx(0, i1, 9600, 0);
//                    int s1=DllUse.instanceDll.StartFormat_ZPL(10,10,100,100);
                    DllUse.instanceDll.DataOrientation_ZPL("N".getBytes("gb18030"));
                    WString data = new WString(qrcode_data.getText().toString());
//                    byte[] data=qrcode_data.getText().getBytes("gb18030");
                    int s=DllUse.instanceDll.StartFormat_ZPL(200,200,40039,10000);
                    int i=DllUse.instanceDll.QRCode_ZPL(data, "M".getBytes("gb18030"), 2, 8);
                    System.out.println("二维码:"+i+" "+s);
                    DllUse.instanceDll.EndFormat_ZPL(port);
                } catch (UnsupportedEncodingException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        });
        PrQr_btn.setBounds(500,300,100,80);
        frame.getContentPane().add(PrQr_btn);
        
        openPort_btn=new JButton("open port");
        openPort_btn.addActionListener(new ActionListener() {    
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                IntByReference i=new IntByReference(0);
                port=DllUse.instanceDll.OpenPortEx(0, i, 9600, 0);
                System.out.println("打开端口:"+port);
            }
        });
        openPort_btn.setBounds(100, 170, 100, 40);
        frame.getContentPane().add(openPort_btn);
        
        closePort_btn=new JButton("close port");
        closePort_btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                DllUse.instanceDll.ClosePort(port);
            }
        });
        closePort_btn.setBounds(100, 270, 100, 40);
        frame.getContentPane().add(closePort_btn);
        
        Text=new JTextField();
        Text.setBounds(300,120,150,40);
        frame.getContentPane().add(Text);
        Text.setColumns(10);
        
        barcode_data=new JTextField();
        barcode_data.setBounds(300,220,150,40);
        frame.getContentPane().add(barcode_data);
        barcode_data.setColumns(10);
        
        qrcode_data=new JTextField();
        qrcode_data.setBounds(300,320,150,40);
        frame.getContentPane().add(qrcode_data);
        qrcode_data.setColumns(10);
    }
    
    public static void main(String[] args) {
            PrinterDemo window=new PrinterDemo();
            window.frame.setVisible(true);
    }
}

在这里插入图片描述
  成功运行javaDemo程序并调用相应动态库成功。

将java程序打包成jar文件

方式一:
在工程根目录下新建一个MANIFEST.MF文件
在这里插入图片描述
文件内容是:
在这里插入图片描述
  MAIN-CLASSK开头需要空格然后写main方法所在的主类的绝对名字,最后回车空出第四行。
  点击项目文件选择export,并输入jar,选择JAR file。
在这里插入图片描述
  选择你要导出的java程序以及第三方包,在JAR file出选择jar包要导出的位置以及jar包名字。
在这里插入图片描述

  • Export generated class files and resources 表示只导出生成的.class文件和其他资源文件
  • Export all output folders for checked projects 表示导出选中项目的所有文件夹
  • Export java source file and resouces 表示导出的jar包中将包含你的源代码*.java,如果你不想泄漏源代码,那么就不要选这项了
  • Export refactorings for checked projects 把一些重构的信息文件也包含进去


  之后选择自己创建的MANIFEST文件,点击finish完成。
在这里插入图片描述
方式二:
选择导出runnable jar
在这里插入图片描述
在这里插入图片描述
关于library handling部分的解释如下:

(1)Extract required libraries into generated JAR。
把所有的import JAR都拆开来,包含在JAR的各个目录中,ex. net/org/xxx.class

(2)Package required libraries into generated JAR。
把所有的import JAR都包在JAR的根目录下

(3)Copy required libraries into a sub-folder next to the generated JAR。
把所有import JAR放在JAR外面独立的一个文件夹

通过上述两种方式就可以将java程序打包成jar文件,并且可以通过终端调用jar文件进行程序的运行。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
注:下文中的 *** 代表文件名中的版本号。 # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【jna-***.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【jna-***.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【jna-***-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: jna-***.jar中文文档.zip,java,jna-***.jar,net.java.dev.jna,jna,***,com.sun.jna,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【jna-***.jar中文文档.zip】,再解压其中的 【jna-***-javadoc-API文档-中文(简体)版.zip】,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件; # Maven依赖: ``` <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>***</version> </dependency> ``` # Gradle依赖: ``` Gradle: implementation group: 'net.java.dev.jna', name: 'jna', version: '***' Gradle (Short): implementation 'net.java.dev.jna:jna:***' Gradle (Kotlin): implementation("net.java.dev.jna:jna:***") ``` # 含有的 Java package(包)(此处仅列举3个): ``` com.sun.jna com.sun.jna.internal com.sun.jna.platform ...... ``` # 含有的 Java class(类)(此处仅列举3个): ``` com.sun.jna.AltCallingConvention com.sun.jna.Callback com.sun.jna.Callback.UncaughtExceptionHandler ...... ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值