JNA

JNA 即 Java Native Access,是一个开源框架,是基于JNI做的封装。主要用于调用C或C++的动态库,达到程序需要实现的效果。
与JNI不同,JNI需要根据java生成.h文件,然后生成对应的DLL,这样会破坏原有的动态库或者需要重新封装一次原有的DLL为新的DLL;JNA则只需要知道调用DLL的.h文件,根据头文件中定义的宏、函数等构造对应的java类和对象,实现Java程序调用已知DLL的效果。

实例阐释

现有已知的.h即头文件如下:

TEST_API.h:定义dll提供的方法;

#ifndef _TEST_API_H__
#define _TEST_API_H__#include "TestEntry.h"#ifndef TEST_API_EXPORTS
#define TESTFUN_API _declspec( dllimport )
#else
#define TESTFUN_API _declspec( dllexport )
#endif#define API_SUCC                              0    // 成功
#define API_FAIL                                1    // 失败typedef int (*TEST_Method1_Evt) (unsigned char code);   // 初始化服务的回调,判断是否成功typedef int (*TEST_Method2_Evt) (unsigned int code, Test_Struct_Entry info, unsigned char finishFlag);   // 获取所有用户的回调,获取C返回的用户结果// 定义回调函数指针
typedef struct
{TEST_Method1_Evt     TestMethod1Ack;TEST_Method2_Evt    TestMethod2Ack;
}TESTEVENTS, *PTESTEVENTS;//初始化服务
extern "C" TESTFUN_API int __stdcall  TEST_OpenService(unsigned int IP,unsigned short Port,PTESTEVENTS events);//查看所有用户
extern "C" TESTFUN_API int __stdcall  TEST_GetSystemUserAll(unsigned char LoginUser[USER_LEN]);    // 登录的用户,后台用于注册校验,此处测试设置为admin#endif

TestEntry.h:定义上述函数使用的参数结构

#ifndef _TEST_H__
#define _TEST_H__#define USER_LEN       30
#define USER_HABBIT_LEN         30
#define USER_COUNT      50//用户信息
typedef struct Nm_User_ProfileInfo
{unsigned char      UserName[USER_LEN];  // 用户名unsigned int     UserAge;             // 用户年龄unsigned char       Habbit[USER_HABBIT_LEN]; // 用户爱好char                Password[30];        // 用户密码
}User_ProfileInfo_Stru;//用户查询返回结果
typedef struct Test_User_Search_Rsp
{unsigned int               Num;User_ProfileInfo_Stru       User_Info[USER_COUNT];
}Test_Struct_Entry;#pragma pack(pop)
#endif

对应的java代码如下:
1.对外提供的方法定义
此处需要注意,32位的DLL和64位的DLL函数名字或许会不一样,可以使用工具Depenency Walker查看。
若此处定义的方法名和DLL里面的函数名不一致,则会导致查不到方法,进而报异常。
所以此处用UnionFunctionMapper 来进行方法名的映射。

public interface TestLib extends StdCallLibrary {   // C 中用__stdcall  定义的函数时,继承StdCallLibrary类//初始化服务public int TEST_OpenService(int ip, short port, TESTAckStruct callback);//查看所有用户public int TEST_GetSystemUserAll();class UnionFunctionMapper implements FunctionMapper {public String getFunctionName(NativeLibrary nativeLibrary, Method method) {if (Platform.is64Bit()) {//dll为64位时候,返回原函数名return method.getName();} else {//dll为32时,返回更改后的函数名,此处是因为32位的DLL函数名称或许和64位的不一样,可以使用Depenency Walker查看具体的名字// 若名字不一样,则会导致方法查不到,进而报异常HashMap<String, String> map = new HashMap<String, String>();map.put("TEST_OpenService", "_TEST_OpenService@12");map.put("TEST_GetSystemUserAll", "_TEST_GetSystemUserAll@0");String name = map.get(method.getName());return name == null ? method.getName() : name;}}}
}

2.TEST_OpenService方法使用的参数TESTAckStruct 构造
定义的参数必须为public类型,否则不会jna不会认。
field里面的顺序必须一致,不一致则会导致数据混乱。

public class TESTAckStruct extends Structure {public AckInterfaceCollection.TEST_Method1_Evt TestMethod1Ack;public AckInterfaceCollection.TEST_Method2_Evt TestMethod2Ack;protected List getFieldOrder() {List<String> list = new ArrayList<String>();list.add("TestMethod1Ack");list.add("TestMethod2Ack");return list;}
}

3.定义回调接口

public class AckInterfaceCollection {public interface TEST_Method1_Evt extends StdCallLibrary.StdCallCallback{int TestMethod1Ack(char code);}public interface TEST_Method2_Evt extends StdCallLibrary.StdCallCallback{int TestMethod2Ack(int code, EntryCollection.Test_Struct_Entry info, char finishFlag);}}

4.参数结构化,对应的结构即为TestEntry.h中定义的结构;
ByReference 是用于指针
ByValue是用于值
定义的参数必须为public,getFieldOrder方法中加入list中的数目和定义的public变量的必须一致,否则会报错。

public class EntryCollection {private final static int USER_LEN = 30;private final static int USER_HABBIT_LEN = 30;private final static int USER_COUNT = 50;public static class User_ProfileInfo_Stru extends Structure {public byte[] UserName = new byte[USER_LEN];     // 用户名public int UserAge;             // 用户年龄public byte[] Habbit = new byte[USER_HABBIT_LEN]; // 用户爱好public byte[] Password = new byte[30];        // 用户密码@Overrideprotected List getFieldOrder() {   // 顺序与上述定义的顺序必须一致,名字也必须一样List<String> field = new ArrayList<String>();field.add("UserName");field.add("UserAge");field.add("Habbit");field.add("Password");return field;}public static class ByReference extends User_ProfileInfo_Stru implements Structure.ByReference {}public static class ByValue extends User_ProfileInfo_Stru implements Structure.ByValue {}}public static class Test_Struct_Entry extends Structure {public int Num;public User_ProfileInfo_Stru[] User_Info = new User_ProfileInfo_Stru[USER_COUNT];@Overrideprotected List getFieldOrder() {List<String> field = new ArrayList<String>();field.add("Num");field.add("User_Info");return field;}public static class ByReference extends Test_Struct_Entry implements Structure.ByReference {}public static class ByValue extends Test_Struct_Entry implements Structure.ByValue {}}}

5.加载动态库文件

public class Operation {protected TestLib testLib;public void setNmsLib() {String libPath = "testlib/TEST_API";if (!Platform.is64Bit()){libPath = "testlib32/TEST_API";}Map<String, Object> options = new HashMap<>();options.put(Library.OPTION_FUNCTION_MAPPER, new TestLib.UnionFunctionMapper());TestLib testLib= (TestLib) Native.loadLibrary(libPath, TestLib.class, options);this.testLib = testLib;}}

6.定义的回调的具体实现

public class AckImpl extends TESTAckStruct {public class TestMethod1Ack implements AckInterfaceCollection.TEST_Method1_Evt {@Overridepublic int TestMethod1Ack(char code) {System.out.println("==========" + code);// TODO: 根据自己需要处理返回值return 0;}}public class TestMethod2Ack implements AckInterfaceCollection.TEST_Method2_Evt{@Overridepublic int TestMethod2Ack(int code, EntryCollection.Test_Struct_Entry info, char finishFlag) {System.out.println("===Code:" + code + "===Info:" + info + "=== finishFlag:" + finishFlag);// TODO: 根据自己需要处理返回值return 0;}}}

7.调用C的方法

public class Test extends Operation {public void openService(int ip, short port) {TESTAckStruct ackStruct = new TESTAckStruct();AckImpl impl = new AckImpl();ackStruct.setTestMethod1Ack(impl.new TestMethod1Ack());  // 设置回调的具体实现ackStruct.setTestMethod2Ack(impl.new TestMethod2Ack());setNmsLib();testLib.TEST_OpenService(ip, port, ackStruct);}public void getSystemUserAll(String user) {if (testLib == null) {setNmsLib();}testLib.TEST_GetSystemUserAll(user);}}

【本章完,后续介绍jna常见的问题以及原因:附上链接 https://blog.csdn.net/m0_37725100/article/details/93998879 】

欢迎关注与指教…

JNA 调用 DLL相关推荐

  1. JNA调用DLL函数遇到的几个问题

    最近一个JSP项目需要用到分词模块,而分词模块实用C++写成的DLL库.于是上网搜各种方法,最后选择了JNA作为JSP调用DLL的工具. JNA(Java Native Access )提供一组Jav ...

  2. 使用Jna调用dll函数库(java使用jna对接硬件接口)

    记录一次项目经历,新公司开发过程中遇到了硬件对接的需求,没有接触过这方面的我一想到这些就很头大,花了几天时间来专门研究一下这个.一般硬件购买后厂家都会附赠一些开发文档,有各种语言的demo,里面其实重 ...

  3. JNA调用dll - java集成一美IP对讲SDK(dll文件)

    项目需要集成一美IP对讲机,一美SDK是dll文件,其他的dll文件集成做法也类似.记录一下 准备 将一美SDK文件的DataTran.dll文件放到系统C:\Windows\System32文件夹里 ...

  4. 使用Java中的jna调用dll

    简介: 在我们日常编码中在与硬件通信或者与其他的c++平台通信的时候经常用java调用dll文件,下面我们介绍俩种使用jna调用dll的方式. 如果是自己部门写的dll文件,一般会有头文件,头文件中会 ...

  5. java中通过JNA调用dll

    ---恢复内容开始--- 1. JNA简单介绍 先说JNI(Java Native Interface)吧,有过不同语言间通信经历的一般都知道,它允许Java代码和其他语言(尤其C/C++)写的代码进 ...

  6. java library jna_Java JNA 调用dll库

    JNA JNA(Java Native Access )提供一组Java工具类用于在运行期间动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JN ...

  7. Java用JNA调用dll : Invalid memory access

    问题描述 java通过JNA调用C/C++ dll时,报Invalid memory access 问题原因 经过分析原因是数据类型不匹配问题 int &a 和 a 的区别 C语言中的a是一个 ...

  8. java jna调用dll文件_关于java jna调用dll的问题

    public interface User32 extends StdCallLibrary { User32 INSTANCE = (User32)Native.loadLibrary(" ...

  9. java web argox打印机 用jna调用dll

    打印机 型号:X-1000VL 用的是PPLB 环境是windowsX64 eclipse jdk1.8(64位) jar包 jna-4.2.2..jar dll : WinPort.dll ,Win ...

最新文章

  1. EasyJWeb-Velocity脚本简明教程
  2. spinbox 上下箭头事件_[React] 3 - 自动绑定 (事件绑定)
  3. 马化腾内部分享:三个问题说透如何做产品
  4. faster_rcnn c++版本的 caffe 封装(1)
  5. java中数值023是什么类型_【Java 教程(原创)】023.参数传值——引用类型参数的传值...
  6. 聊聊高并发(二十四)解析java.util.concurrent各个组件(六) 深入理解AQS(四)
  7. 管道( Pipeline )模型--示例
  8. DCMTK3.5.4与3.6.0版本的区别
  9. 德州扑克AI--Programming Poker AI(译)
  10. 游戏开发之类和对象的基本概念(C++基础)
  11. 区块链 Fisco bcos 智能合约(13)-Solidity的设计模式
  12. 如何使用U盘制作Windows 7安装盘
  13. html app5 仿微信朋友圈,uniapp仿微信聊天App界面|仿微信朋友圈|uniapp仿微信
  14. 购买周期 python-用Python实现一个基于EG协整法的跨周期套利策略
  15. GD32F103串口DMA收发
  16. 微信小程序即时聊天前后端(TP5+Gateway)
  17. 利用xiaopiu做产品原型输出与交互设计
  18. 一个3D城市地图应用开发工具,等你获取 ThingJS 3D 全景 可视化
  19. 小米微信自动加好友appium
  20. Qt之Windows下禁用中文输入法

热门文章

  1. 关于小程序支付后的强制关注公众号问题总结
  2. influxdb入门
  3. unity Scene文件保存的内容
  4. 使用免费RPA软件系统 构件自己的自动化流程 安装配置教程
  5. [百战成神4]C语言之凡人暴刷小牛【超详细解析,掌握每道题】
  6. 优化BIOS加快电脑启动和运行速度
  7. Python实现信用评分模型
  8. 桌面快捷方式的图片看不见了怎么办?
  9. Openpyxl 总结
  10. 树莓派盒子性能监控管理