利用jna调用dll(史上最全) 您所在的位置:网站首页 如何调用dll中的接口类型文件 利用jna调用dll(史上最全)

利用jna调用dll(史上最全)

2024-06-08 01:33| 来源: 网络整理| 查看: 265

java利用jna调用dll(史上最全) 内容说明jna介绍用到的工具及资料dll中的内容java中利用jna模拟dll中的结构体(利用接口中的内部类模拟)调用dll主程序利用jna调用dll需要注意的问题总结

内容说明

本文主要是我在做项目中,甲方用的java开发的平台,我们写算法嵌入到他们的系统中,本来以为直接用java写就OK了,可是他们要求用c++写说速度快(说实话只要不操作硬件,现在的java虚拟机运行java和c++的执行效率几乎一样)(没办法,只能使用java调用c++生成的dll),这里就不赘述生成dll的方法了,网上多的很。本文主要介绍利用jna调用dll的具体实现,以及在实现过程遇到的坑,基本上含盖了所有内容。 在这期间我使用过

jna介绍

大白话解释就是jna是用来调用dll的jar包,是对jni技术的一个升级,使用起来比jni方便许多。

用到的工具及资料

1.idea2019创建的java的Maven项目; 2.vs2019生成的dll 3.jna的jar包:因为例子是用Maven项目做的,jar包坐标如下:

com.sun.jna jna 3.0.9

4.jna的官方文档如下(看里面的数据类型转换就可以了,其他看我的例子就ok): 链接:https://java-native-access.github.io/jna/4.2.1/overview-summary.html.

有了上面的准备,下面就开始我们的例子了。

dll中的内容

首先用vs2019写的c++dll的程序如下,该例子主要演示java和c++中的char*、int、double的类型对应(其他的去上面链接的官方文档中寻找),以及对应参数是结构体以及结构体中嵌套结构体,函数返回值也为结构体以及结构体中嵌套结构体。

#define dllTest _declspec(dllexport) #pragma once #include #include #include #include using namespace std; struct myStruct { int a; char* steel; int b; }; struct myStructs { myStruct mS[10]; int count; }; extern "C" { dllTest myStruct allroundTest(int i, int j, char* s) { mystru.a = i; mystru.b = j; mystru.steel = s; return mystru; } dllTest myStructs* arrayFun(myStructs* ms) { return ms; } dllTest char* returnChar(myStructs* ms, int i) { char* res = ms->mS[i].steel; return res; } dllTest char* returnString(char* ms) { return ms; } dllTest int addNormal(myStruct ms) { return ms.b + ms.a; } dllTest int* test01(int* a) { return a; } dllTest void addPrt(myStruct* ms, int* ret) { *ret = ms->a + ms->b + 1; } dllTest int addRef(myStruct& ms) { return ms.a + ms.b + 2; } } java中利用jna模拟dll中的结构体(利用接口中的内部类模拟)

注意,其中对应结构体中的属性的顺序以及属性名必须和dll中保持一致,还有注意dll存放的位置,我是直接放到jdk的bin目录下,结构体中的ByValue以及ByReference分别对应c++中的引用和指针。

package com.tz; import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Structure; import com.sun.jna.ptr.IntByReference; public interface dllTestApi extends Library { //需将dll放进jdk的bin目录下 public static dllTestApi dta = (dllTestApi) Native.loadLibrary("PanAlgDLL", dllTestApi.class); public static class myStructur extends Structure { public static class ByReference extends myStructur implements Structure.ByReference{ } public static class ByValue extends myStructur implements Structure.ByValue{ } public int a; public String steel; public int b; } public static class myStructurs extends Structure { public static class ByReference extends myStructurs implements Structure.ByReference{ } public static class ByValue extends myStructurs implements Structure.ByValue{ } public myStructur.ByValue[] structs = new myStructur.ByValue[10]; public int count; } int addNormal(myStructur.ByValue ms); void addPrt(myStructur.ByReference pms, IntByReference sum); int addRef(myStructur.ByReference rms); myStructurs.ByReference arrayFun(myStructurs.ByReference ms); String returnString(String ms); IntByReference test01(IntByReference a); String returnChar(myStructurs.ByReference ms, int i); myStructur.ByValue allroundTest(int i, int j, String s); } 调用dll主程序

下面是调用dll中的方法的测试程序:

package com.tz; import com.sun.jna.ptr.IntByReference; public class Test01 { public static void main(String[] args) { System.setProperty("jna.encoding", "GBK"); dllTestApi.myStructur.ByReference pmysStructur = new dllTestApi.myStructur.ByReference(); pmysStructur.a = 1; pmysStructur.b = 3; IntByReference ib = new IntByReference(); dllTestApi.dta.addPrt(pmysStructur,ib); System.out.println(ib.getValue()); System.out.println(dllTestApi.dta.addRef(pmysStructur)); dllTestApi.myStructur.ByValue vmysStructur = new dllTestApi.myStructur.ByValue(); vmysStructur.a = 1; vmysStructur.b = 3; System.out.println(dllTestApi.dta.addNormal(vmysStructur)); IntByReference ibf = new IntByReference(2); ibf.setValue(3); ibf.setValue(4); IntByReference res = dllTestApi.dta.test01(ibf); int[] re = res.getPointer().getIntArray(0, 3); System.out.println(re[0]); dllTestApi.myStructur.ByValue pmys1 = new dllTestApi.myStructur.ByValue(); pmys1.b = 1; pmys1.steel = "abcf"; pmys1.a = 1; dllTestApi.myStructur.ByValue pmys2 = new dllTestApi.myStructur.ByValue(); pmys2.a = 2; pmys2.steel = "asdg"; pmys2.b = 2; dllTestApi.myStructurs.ByReference pmyss = new dllTestApi.myStructurs.ByReference(); pmyss.structs[0] = pmys1; pmyss.structs[1] = pmys2; pmyss.count = 2; dllTestApi.myStructurs.ByReference ress = dllTestApi.dta.arrayFun(pmyss); System.out.println(ress.count); System.out.println(ress.structs[1].a); String rS = dllTestApi.dta.returnChar(pmyss, 0); System.out.println(rS); String str11 = dllTestApi.dta.returnString("666"); System.out.println(str11); dllTestApi.myStructur.ByValue reess = dllTestApi.dta.allroundTest(6, 6, "tz"); System.out.println(reess.a); System.out.println(reess.steel); } } 利用jna调用dll需要注意的问题

1、想要调用dll中的方法,且调用的方法需要结构体数组参数或者返回值是结构体数组,我们知道c++方法对于结构体数组参数处理起来比较麻烦,所以我解决的办法就是加一个结构体,该结构体中包含结构体数组以及包含的个数,如上面的例子所示; 2、当java要接收dll方法返回结构体参数,尤其当结构体中包含char*时,我们需要在java中将结构体实例化当作参数传入要调用的dll中,并在dll中将要返回的结构体传给java中当作参数的结构对象,不然会报莫名其妙的错(我调试了好久才发现的)。

总结

以上就是java利用jna调用dll的小例子,例子虽小,五脏俱全,基本上涵盖了所有的内容。研究不易,如果该文章对您有帮助,希望



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有