目录

1、简介

2、原理

3、配置环境,创建demo

3.1 搞清楚.dll/.so文件适用环境

3.2 创建一个普通的maven项目

3.2.1 将.dll/.so文件放在resources根路径下

3.2.2 pom.xml文件添加jna依赖

3.2.3 编写一个CLibrary接口,继承Library接口

3.2.4 编写一个测试类调用c++函数代码VixHz_InitSDK()

4、调用JNA过程遇到的问题及解决方法


1、简介

提到JNA 就不得不提一下JNI(Java Native Interface),有过不同语言间通信开发经历的一般都知道,它允许java和其他语言代码(尤其是C/C++)进行交互,只要遵守约定即可。首先看下JNI调用C/C++过程,注意写程序时自下而上,调用时自上而下:

可见步骤之多,调用.dll/.so共享库之痛苦的过程。

若已有编译好的.dll/.so文件—>需先用是C语言另外写一个.dll/.so共享库,使用SUN规定的数据结构代替C语言的数据结构,调用已有的dll/so中公布的函数—>java中载入这个库—>java编写Native函数作为链接库中函数的代理

问题是很少有java程序员愿意编写调用.dll/.so库中原生函数的java程序,这也使java在客户端上乏善可言,是JNI的一大弱点!

但是JNA不能完全替代JNI,JNI不仅可以实现java访问C,也可实现C调用java。

而JNA只能实现Java访问C函数,作为一个Java框架,自然不能实现C语言调用Java代码。此时,你还是需要使用JNI技术。

那什么是JNA呢?

JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架。

JNA框架就是为了解决上述JNI弱点而开发的,它提供一组java工具类用于在运行期间动态访问系统本地共享类库,java开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射,而不需要编写任何Native/JNI代码,大大降低了Java调用本体共享库的开发难度。

之所以说它是JNI的替代者,是因为JNA大大简化了调用本地方法的过程,使用很方便,基本上不需要脱离Java环境就可以完成。JNA调用C/C++的过程大致如下:

可以看到步骤减少了很多,最重要的是我们不需要重写我们的动态链接库文件,而是有直接调用的API,大大简化了我们的工作量。

2、原理

JNA使用一个小型的JNI库插桩程序来动态调用本地代码。开发者使用java接口描述目标本地库的功能和结构,这使得它很容易利用本机平台的功能,而不会产生多平台配置和生成JNI代码的高开销。这样的性能、准确性和易用性显然受到很大的重视。此外JNA包括一个已与许多本地函数映射的平台库,以及一组简化本地访问的共用接口。

注意:

JNA是建立在JNI技术基础之上的一个java类库,它提供了一个动态的C语言编写的转发器,可以自动实现java和C的数据类型映射,不需要再编写C动态链接库,可方便使用java直接访问动态链接库中的函数,JNA性能上有些微损失。

3、配置环境,创建demo

3.1 搞清楚.dll/.so文件适用环境

示例代码是根据不同的环境调用不同的动态链接库:

public class JnaUtil {public static Logger logger = Logger.getLogger(JnaUtil.class);static CLibrary INSTANCE;public static CLibrary LED_INSTANCE;static {// 获取jdk位数String bits = System.getProperty("sun.arch.data.model");// 获取os名称String ops = System.getProperty("os.name");logger.info("jdk bits=" + bits);logger.info("option sysetm=" + ops);if (ops.startsWith("win") || ops.startsWith("Win"))//windows{if ("32".equals(bits)) {logger.info("use CCR_SDKx32.dll");INSTANCE = (CLibrary) Native.loadLibrary("CCR_SDKx32.dll", CLibrary.class);}if ("64".equals(bits)) {logger.info("use CCR_SDKx64.dll and LEDControl_x64.dll");INSTANCE = (CLibrary) Native.loadLibrary("CCR_SDKx64.dll", CLibrary.class);LED_INSTANCE = Native.loadLibrary("LEDControl_x64.dll", CLibrary.class);}} else {if ("32".equals(bits)) {logger.info("use libCCR_SDKx64-x86_32.so");INSTANCE = (CLibrary) Native.loadLibrary("libCCR_SDKx64-x86_32.so", CLibrary.class);}if ("64".equals(bits)) {logger.info("use libCCR_SDKx64-x86_64.so and libLEDControl-x86_64.so");INSTANCE = (CLibrary) Native.loadLibrary("libCCR_SDKx64-x86_64.so", CLibrary.class);LED_INSTANCE = Native.loadLibrary("libLEDControl-x86_64.so", CLibrary.class);}}}
}

java环境的jdk位数要与.dll/.so位数相同,否则会报类似错误:

java.lang.UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序。

3.2 创建一个普通的maven项目

3.2.1 将.dll/.so文件放在resources根路径下

(若放在子包中,也是可以加载库文件的,不放心可在Native.loadLibrary()中制定下库文件路径)

3.2.2 pom.xml文件添加jna依赖

建议jna包的版本不要太老旧:

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

3.2.3 编写一个CLibrary接口,继承Library接口

public interface CLibrary extends Library {CLibrary INSTANCE = Native.loadLibrary("iNetSDK.dll", CLibrary.class);/*** 初始化SDK 注意:调用SDK其他接口前必须先调用此接口!** @return TRUE表示成功,FALSE表示失败*/boolean VixHz_InitSDK();
}

3.2.3.1 在上面的代码中,我们定义了一个接口,继承自Library 或StdCallLibrary,默认的是继承Library ,
如果动态链接库里的函数是以stdcall方式输出的,那么就继承StdCallLibrary,比如众所周知的kernel32库。

接口中使用的函数必须与链接库中的函数原型保持一致。

3.2.3.2 接口内部定义

接口内部需要一个公共静态常量:INSTANCE,通过这个常量,就可以获得这个接口的实例,从而使用接口的方法,也就是调用外部dll/so的函数。
该常量通过Native.loadLibrary()这个API函数获得,该函数有2个参数:

  • 第一个参数是动态链接库dll/so的名称,但不带.dll或.so这样的后缀(此处加了后缀,不同系统和环境已经适用了不同的库文件),这符合JNI的规范,因为带了后缀名就不可以跨操作系统平台了。搜索动态链接库路径的顺序是:当前类当前文件夹,找不到——再在工程当前文件夹下面找win32/win64文件夹,找到后搜索对应的dll文件,找不到——到WINDOWS下面去搜索,再找不到——抛异常。

  • 第二个参数是本接口的Class类型。JNA通过这个Class类型,根据指定的.dll/.so文件,动态创建接口的实例。该实例由JNA通过反射自动生成。

3.2.4 编写一个测试类调用c++函数代码VixHz_InitSDK()

@RunWith(SpringRunner.class)
@SpringBootTest
public class DeviceSdkApplicationTests {/*** 初始化SDK*/@Testpublic void testVixHz_InitSDK() {boolean initSDKResult = CLibrary.INSTANCE.VixHz_InitSDK();System.out.println("initSDKResult = " + initSDKResult);}
}

运行结果,类型简单的JNA调用成功:

4、调用JNA过程遇到的问题及解决方法

4.1 调用JNA报的错java.lang.Error: Invalid memory access:很大可能是JNA调c++接口类型映射的问题;

类型复杂涉及到指针和结构体,接下来总结下JNA实战笔记汇总(二)——JNA和C / C ++的数据类型映射

JNA实战笔记汇总(一)—— JNA简介及demo环境创建相关推荐

  1. JNA实战笔记汇总一 简单认识JNA|成功调用JNA

    一.简介 先说JNI(Java Native Interface)吧,有过不同语言间通信经历的一般都知道,它允许Java代码和其他语言(尤其C/C++)写的代码进行交互,只要遵守调用约定即可.首先看下 ...

  2. JNA实战笔记汇总(二)——JNA和C / C ++的数据类型映射(dll函数回调、结构体、指针)

    目录 JNA技术难点 1.函数回调 2.结构体 3.指针 JNA技术难点 有过跨平台.跨语言开发的程序员都知道,跨平台.预研调用的难点,就是不同语言之间数据类型不一致造成的问题.绝大部分跨平台调用的失 ...

  3. c++ jna 数据类型_JNA实战笔记汇总一 简单认识JNA|成功调用JNA

    一.简介 先说JNI(Java Native Interface)吧,有过不同语言间通信经历的一般都知道,它允许Java代码和其他语言(尤其C/C++)写的代码进行交互,只要遵守调用约定即可.首先看下 ...

  4. shell 脚本实战笔记(7)--集群网络相关知识和环境搭建

    前言: 对网络相关的知识, 做下笔记. 包括IP地址A/B/C的分类, 静态地址的配置/DNS配置, 以及网卡相关信息查看. *) A/B/C/D类网络地址的划分 IP地址=网络地址+主机地址 或 I ...

  5. JNA实战系列:第一个简单的JNA开发程序

    文章目录 第一个简单的JNA的开发程序 一.引入依赖包 二.创建一个接口,继承Libary类 三.在Java中使用dll中封装的方法 总结: JNA中调用C.C++DLL或者.so库中的函数的步骤总结 ...

  6. 哈佛大学单细胞课程|笔记汇总 (五)

    生物信息学习的正确姿势 NGS系列文章包括NGS基础.在线绘图.转录组分析 (Nature重磅综述|关于RNA-seq你想知道的全在这).ChIP-seq分析 (ChIP-seq基本分析流程).单细胞 ...

  7. 阿里巴巴中台战略思想与架构实战笔记

    阿里巴巴中台战略思想与架构实战笔记 序言一 序言二 第一部分 引子 第1章 阿⾥巴巴集团中台战略引发的思考 1.1 阿⾥巴巴共享业务事业部的发展史 1.2 企业信息中心发展的症结 "烟囱式& ...

  8. RT-Thread实战笔记|MPU6050使用详解及DMP姿态解算

    小伙伴们大家好,好久不更新RT-Thread实战笔记啦,今天来搞一搞MPU6050,话不多说,淦! 本章源码获取 欢迎文末留言区或者公众号后台回复"MPU6050"即可获取本教程源 ...

  9. R语言实战笔记--第十五章 处理缺失数据

    R语言实战笔记–第十五章 处理缺失数据 标签(空格分隔): R语言 处理缺失数据 VIM mice 缺失值(NA),是导致我们计算错误的一大来源,处理缺失数据在实际的应用中有着较为重要的作用. 基本方 ...

最新文章

  1. iOS自定义简易刷新视图(仿MJRefresh)
  2. 戴尔推免费浏览器安全工具 可隔离恶意软件
  3. Android加载/处理超大图片神器!SubsamplingScaleImageView(subsampling-scale-image-view)【系列1】...
  4. 微信群「斗图」总输,Python助我超神!
  5. 2019-05-15 Java学习日记 day5
  6. WebBenchmark之动态数据测试
  7. [No0000D7]img生成器.bat合并所有图片到html网页中
  8. 搜索 —— 暴力搜索
  9. STM32 - 定时器的设定 - 基础- 0A - Timers and external trigger synchronization - 定时器和外部触发的同步
  10. mysql要将语句反复执行15次_MySQL多表查询疑问
  11. 收藏!盘点B站up主们最喜欢用的录屏软件!
  12. “麻将换皮”的《刀塔自走棋》会是下一个“吃鸡”吗?
  13. 区块链开发用什么语言好?
  14. 重建同义词+oracle,oracle 创建同义词
  15. MTK移植大全(参考)建议收藏!
  16. 三大条件致病菌|大肠埃希氏菌、血链球菌、李斯特菌
  17. XGBOOST的基本原理以及使用
  18. alter在MySQL中是什么意思_MySql中要AlterTable的同学请注意!!!_MySQL
  19. 【OPENCV_系列电子PDF图书连载】计算机视觉从入门到精通完整学习路线专栏
  20. 热插拔机制之udev和mdev

热门文章

  1. error C2146 和C4430 错误
  2. python编程入门指南磁力下载-菜鸟边学Python边实践之打造自己的磁力搜索神器
  3. 2023最新8个电脑必装软件,新电脑装完好用又高效
  4. Office2021版64位+mathtype6.9
  5. 【SpringSSM项目】搏击俱乐部 拦截未登录的用户
  6. 百度网盘分享出去文件不存在_百度网盘分享文件被取消了怎么办?找回被取消分享文件的方法...
  7. 有趣!用计算机视觉技术与PaddlePaddle打造AI控烟项目
  8. 新年趣事之打牌_DP
  9. 深度主动学习综述2020
  10. 在dmesg中打印_dmesg七种用法