使用Java中的jna调用dll

简介:
在我们日常编码中在与硬件通信或者与其他的c++平台通信的时候经常用java调用dll文件,下面我们介绍俩种使用jna调用dll的方式。

如果是自己部门写的dll文件,一般会有头文件,头文件中会对dll中的方法进行说明包括他的方法名、入参、出参。如果是外部dll文件的话一般也会有文本介绍dll中的方法名、入参和出参,而且如果外部的dll一般都有java的sdk示例。
但是一般自己同事写dll的时候,在开始的时候多少是会出现问题的。我们可以使用工具dependency walker查看dll中是否有可以使用的方法,如下图所示。
在这里插入图片描述
然后我们使用第一种jna调用的方法来调用dll文件来执行fnComputPk方法。
从它的头文件我们可以查看到具体的方法。

extern "C" MONTECARLOPK_API int fnComputPK( );

从头文件中可以看到这个方法没有输入参数,只有一个输出参数。在使用jna的时候,需要引入jna,

<dependency>
			<groupId>net.java.dev.jna</groupId>
			<artifactId>jna</artifactId>
			<version>4.1.0</version>
</dependency>

代码示例如下:

import com.sun.jna.Function;
import com.sun.jna.NativeLibrary;


/**
 * 尝试jna调用动态链接库(dll)
 */
public class JnaDemo {
//   static NativeLibrary library = NativeLibrary.getInstance("C:\\Windows\\System32\\msvcrt");
//   static NativeLibrary library = NativeLibrary.getInstance("C:\\Windows\\System32\\msvcrt.dll");
   static NativeLibrary library = NativeLibrary.getInstance("D:\\javadeveloping\\java\\hsjs\\dd\\MonteCarloPK.dll");


    /**
     * 调用dll有返回值函数
     *
     * @param functionName 函数名
     * @param clazz        T类型Class
     * @param params       入参
     * @param <T>          返回类型
     * @return dll函数返回值
     */
    public static <T> T invoke(String functionName, Class<T> clazz, Object... params) {
        Function function = library.getFunction(functionName);
        Object invoke = function.invoke(clazz, params);
        return clazz.cast(invoke);
    }

    /**
     * 调用dll无返回值函数
     *
     * @param functionName 函数名
     * @param params       入参
     */
    public static void invoke(String functionName, Object... params) {
        Function function = library.getFunction(functionName);
        function.invoke(params);
    }

    /**
     * 生成dll函数
     *
     * @param functionName 函数名
     * @return dll函数
     */
    public static Function function(String functionName) {
        return library.getFunction(functionName);
    }

    /**
     * 测试
     */
    public static void main(String[] args) {
        int i=invoke("fnComputPK",Integer.class,null);
        System.out.println("输出的是:"+i);
       	 /*Double pow = invoke("pow", Double.class, 2d, 2d);
        Double sqrt = invoke("sqrt", Double.class, 2d);
        invoke("printf", "%f \n", Math.PI);
        invoke("printf", "%g \n", pow);
        invoke("printf", "%g \n", sqrt);
        invoke("printf", "%s \n", "qweqweqweqwe");
        invoke("printf", "%d \n", 4);*/
    }
}

但是这里容易出现一个错误就是你的dll文件路径命名是写对了,但是它还是会报找不到dll文件。
在这里插入图片描述
其实我在这个路径下是有文件的。
在这里插入图片描述
但是依然会报错。
在这里插入图片描述
这里报错可能和dll的打包方式有关系,我这里原因是dll一开始打包是以32位的debug的模式打的包,最后又使用32位的relise就可以正常访问了。

以上是一种方式,还有另一种使用jna调用dll的方式,就是你把dll的头文件转换的你的java接口形式,在加载dll的时候把它赋给一个它对应的接口,这里我就用佳博打印机的代码说明这个调用方式:

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

import com.sun.jna.Library;
import com.sun.jna.Native;
public class JavaTest 
{

	public interface TscLibDll extends Library
	{		
		TscLibDll INSTANCE = (TscLibDll) Native.loadLibrary("\\TSCLIB", TscLibDll.class);
        int about ();
        int openport (String pirnterName);
        int closeport ();
        int sendcommand (String printerCommand);
        int sendBinaryData (byte[] printerCommand, int CommandLength);
        int setup (String width,String height,String speed,String density,String sensor,String vertical,String offset);
        int downloadpcx (String filename,String image_name);
        int barcode (String x,String y,String type,String height,String readable,String rotation,String narrow,String wide,String code);
        int printerfont (String x,String y,String fonttype,String rotation,String xmul,String ymul,String text);
        int clearbuffer ();
        int printlabel (String set, String copy);        
        int windowsfont (int x, int y, int fontheight, int rotation, int fontstyle, int fontunderline, String szFaceName, String content);
        int windowsfontUnicode(int x, int y, int fontheight, int rotation, int fontstyle, int fontunderline, String szFaceName, byte[] content);
        int windowsfontUnicodeLengh(int x, int y, int fontheight, int rotation, int fontstyle, int fontunderline, String szFaceName, byte[] content, int length);
        byte usbportqueryprinter();
        
	}
    public static void main(String[] args)
    {

        String WT1 = "TSC Printers";
        String B1 = "20080101";

    	//unicode format
    	byte[] result_unicode = new byte[1024];
    	String word_unicode = "简体中文测试123123繁體測試";
    	result_unicode = word_unicode.getBytes(StandardCharsets.UTF_16LE);

    	//utf-8 format
    	byte[] result_utf8 = new byte[1024];
    	String word_utf8 = "TEXT 40,620,\"ARIAL.TTF\",0,12,12,\"utf8 test Wörter auf Deutsch\"";
    	result_utf8 = word_utf8.getBytes(StandardCharsets.UTF_8);

    	
        //TSCLIB_DLL.about();
        byte status = TscLibDll.INSTANCE.usbportqueryprinter();//0 = idle, 1 = head open, 16 = pause, following <ESC>!? command of TSPL manual
        TscLibDll.INSTANCE.openport("TSC TE210");
        TscLibDll.INSTANCE.sendcommand("SIZE 100 mm, 120 mm");
        TscLibDll.INSTANCE.sendcommand("SPEED 4");
        TscLibDll.INSTANCE.sendcommand("DENSITY 12");
        TscLibDll.INSTANCE.sendcommand("DIRECTION 1");
        TscLibDll.INSTANCE.sendcommand("SET TEAR ON");
        TscLibDll.INSTANCE.sendcommand("CODEPAGE UTF-8");
        TscLibDll.INSTANCE.clearbuffer();
        TscLibDll.INSTANCE.downloadpcx("\\UL.PCX", "UL.PCX");
        TscLibDll.INSTANCE.windowsfont(40, 490, 48, 0, 0, 0, "Arial", "Windows Font Test");
        TscLibDll.INSTANCE.windowsfontUnicodeLengh(40, 550, 48, 0, 0, 0, "Arial", result_unicode,word_unicode.length());
        TscLibDll.INSTANCE.sendcommand("PUTPCX 40,40,\"UL.PCX\"");
        TscLibDll.INSTANCE.sendBinaryData(result_utf8, result_utf8.length);
        TscLibDll.INSTANCE.barcode("40", "300", "128", "80", "1", "0", "2", "2", B1);
        TscLibDll.INSTANCE.printerfont("40", "440", "0", "0", "15", "15", WT1);
        TscLibDll.INSTANCE.printlabel("1", "1");
        TscLibDll.INSTANCE.closeport();  	
    }
  
}

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枣泥馅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值