Java通过JNA调用so库 Linux环境

article/2025/10/8 4:23:44

记录一下自己的JNA调研成果,需求是公司同事用C++写了一个红外测温SDK,编译成so文件后提供给客户使用。客户需要一个Linux环境用Java调用so库的一个demo,刚好就我一个懂点Java,所有有了这次调研。

因为JNA相关资料实在太少,而且我一没用过Linux,二没搞过虚拟机,所以在研发过程中踩了太多坑,每向前迈一步都要克服很多困难,所以想记录下来,也许能给其他需要的人借鉴一下,少走一点弯路。Linux虚拟机Java开发环境我就不介绍了,这方面资料还是挺多的,主要说一下JNA的使用。

JNA介绍和技术原理

JNA全称Java Native Access,是一个建立在经典的JNI技术之上的Java开源框架。

JNA提供工具用于调用c/c++动态函数库(如Window的dll以及linux的so)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标函数库的函数与结构,JNA将自动实现Java接口方法到函数的映射。

JNA使用一个小型的JNI库插桩程序来动态调用本地代码。开发者使用Java接口描述目标本地库的功能和结构,这使得它很容易利用本机平台的功能,而不会产生多平台配置和生成JNI代码的高开销。这样的性能、准确性和易用性显然受到很大的重视。

此外,JNA包括一个已与许多本地函数映射的平台库,以及一组简化本地访问的公用接口。

注意:

JNA是建立在JNI技术基础之上的一个Java类库,它使您可以方便地使用java直接访问动态链接库中的函数。

原来使用JNI,你必须手工用C写一个动态链接库,在C语言中映射Java的数据类型。

JNA中,它提供了一个动态的C语言编写的转发器,可以自动实现Java和C的数据类型映射,你不再需要编写C动态链接库。

也许这也意味着,使用JNA技术比使用JNI技术调用动态链接库会有些微的性能损失。但总体影响不大,因为JNA也避免了JNI的一些平台配置的开销。

JNA数据类型映射表&模拟指针

 

在JNA中模拟指针,最常用到的就是Pointer类和PointerByReference类。Pointer类代表指向任何东西的指针,PointerByReference类表示指向指针的指针。Pointer类更加通用,事实上PointerByReference类内部也持有Pointer类的实例。

 

使用示例

环境说明:

jna-version:4.0.0(我用的是4.0.0版本)

jdk-version:1.8

java开发使用idea

JNA下载地址:https://github.com/java-native-access/jna.git

1、JNA简单调用

实现步骤

在Java类中创建一个接口CLibrary继承Library,

在CLibrary中加载so文件,

创建一个本地方法(对应so中的提供的native方法),

在main函数中用so实例(INSTANCE)调用本地创建的方法。

注意:下面是So库提供的可调用的方法.h头文件代码,JNA就是实现Java对这些函数的调用,后面的例子都是实现对这些方法的调用。

 

Java代码

 

(Linux中加载libSCT_SDK_CHANNEL_X64.so,要去掉前面的lib和.so后缀)这里so文件SCT_SDK_CHANNEL_X64依赖SCT_SDK_MT_X64,所以要先加载SCT_SDK_MT_X64

CLibrary中创建了SCT_ChannelInit()方法,根据头文件,返回int类型,后面就可以用INSTANCE1去调用本地方法映射的so库函数了。Main方法中调用CLibrary创建的SCT_ChannelInit()方法,打印输出结果。

 

运行,返回1调用成功

 

2、JNA返回char指针

实现步骤

同上

 

从.h头文件我们可以看到,要调用的C++函数,返回值是char*(字符类型指针),参考映射表,我们可以用字符串接收返回数据。

Java代码

在CLibrary中创建SCT_ChannelVersion();

 

Main函数中调用本地方法

 

运行,返回结果

 

3、JNA返回void指针

实现步骤

同上

 

从.h头文件看到返回的是HChannel类型,它是C++自定义的void指针

 

参考映射表,我们可以用Pointer(通用,所有指针都可以用Pointer接收)

Java代码

首先定义一个Pointer并申请内存,然后在CLibrary中创建SCT_ChannelCreate();

 

 

Main中接收指针,pChannel会在后面的例子中用到

 

4、JNA基本传参

实现步骤

同上

 

从.h头文件中可以看到需要参数hChannel,返回int类型

Java代码

同样在CLibrary中创建本地函数SCT_ChannelClose(Pointer hChannel);

 

Main函数中传入hChannel参数调用

 

运行,打印输出,返回1,调用成功

 

5、JNA模拟结构体传参

实现步骤

同上

 

从.h头文件中看到需要参数hChannel和openParams,OpenParams是一个结构体指针,我们要在Java中模拟结构体openParams,返回结果int类型

先查看一下C++中结构体OpenParams

 

Java代码

 

模拟OpenParams结构体,创建OpenParams继承Structure,设置成员变量,和C++结构体保持一致,参考映射表,char对应byte,int对应int,CapabilitySet也是结构体,属于结构体嵌套,CapabilitySet结构体模拟参考OpenParams,(JPEG_SIZE是枚举类型)C++中枚举类型和Java中不同,Java直接用int接收就可以。

创建两个内部类ByReference,ByValue继承OpenParams,分别实现接口Structure.ByReference、Structure.ByValue

覆盖getFieldOrder()方法,按顺序添加成员变量,一定要和C++结构体保持一致。

结构体传参分为值传递、引用传递(指针传递)

值传递使用ByValue

引用传递使用ByReference

在CLibrary中创建SCT_ChannelOpen(Pointer hChannel, OpenParams.ByRefrence openParams);

 

在main函数中初始化结构体

 

然后调用,OPEN_SUCCESS=1,调用成功

 

 

6、JNA模拟结构体数据传递

实现步骤

同上

 

从.h头文件中看到需要传入三个参数,hChannel指针,packetType枚举类型,param void指针,先看看C++中Packet Type,例如其中RTR_GetJpgFrame获取的数据param对应是一个FrameInfo结构体指针,所以要读取数据,我们要模拟结构体FrameInfo进行数据传递

 

看看C++中FrameInfo结构体,一共四个成员变量,char指针指向的是图片jpg的二进制地址,len表示二进制数据长度,windth,height宽高

 

Java代码

枚举类型,也可以直接传int值

 

模拟创建FrameInfo结构体继承Structure,设置成员变量参考映射表,创建两个内部类ByReference、ByValue,char指针我们可以用Pointer表示,注意需要给Pointer申请内存

 

先声明一个imgbyte用来接收二进制数据

 

在CLibrary中创建SCT_ChannelRead(Pointer hChannel, int packetType,Frame Info.ByReference frameInfo);

 

在main函数中初始化FrameInfo结构体并调用SCT_ChannelRead()方法,如果调用成功,读取_pData,保存成图片

 

 

运行,返回结果1,成功保存图片readjpg

 

 

7、JNA模拟结构体回调方法

调用步骤

同上

 

从.h头文件可以看到需要hChannel指针,optionType枚举类型,param void指针三个参数

先查看OptionType,例如OT_SetFunGetMtData类型,param指向的是一个回调函数FunGetMtData();

 

查看FunGetMtData回调方法,我们需要在Java中实现该回调

 

查看C++结构体MtImgInfo,我们现在就读取这个结构体数据

 

Java代码

枚举类型参考上面

 

现在模拟创建MtImgInfo结构体继承Structure,设置成员变量参考映射表,创建两个内部类ByReference、ByValue,获取数据,要想获取回调方法FunGetMtImgInfo()中其他数据,可以用同样的方法

 

在CLibrary中创建本地方法SCT_ChannelSetOpt(Pointer hChannel, int optionType,CallBack callback);形参callback创建请看下一步

 

在CLibrary中定义一个回调接口CallBack继承Callback,并在接口内创建一个FunGetMtData方法对应C++中的回调方法

 

在CLibrary创建FunGeMtData实现接口CallBack并实现FunGetMtData()方法

 

在main函数中调用本地方法SCT_ChannelSetOpt();

 

运行查看回调结果,成功输出回调结果

 写了这么多,差不多各种类型的例子都有了,如果有哪里不对的,或者有问题需要的探讨的,可以留言。


http://chatgpt.dhexx.cn/article/fnKjJ46b.shtml

相关文章

JNI便捷开发框架JNA框架之入门(一)

一、JNA介绍 JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架。它提供一组Java工具类用于在运行期动态访问系统本地共享类库而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中…

JNA简介

2019独角兽企业重金招聘Python工程师标准>>> JNA JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只…

JNA的概念

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

Java 之 JNA(调用第三方库)

是什么? 一、了解JNA之前,我们先了解一下JNA的前身JNI(Java Native Interface):通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植。 [1] 从Java1.1开始,JNI标准成为java平台…

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

目录 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 编写…

ROW(行)与COLUMN(列)

数列数,COLUMNS(A:B)2,即A到B一共两列。

column函数HTML5,column函数 excel中column函数的使用方法

column函数是一种查询的工具,我相信许多人都不会使用到这一个函数,因此在实际工程当中并不是十分的常见,然而这一款韩束如果能够掌握,对我们的工作也是非常有帮助的,接下来我们就一起来好好的了解一下这个函数究竟该如何使用。 column函数——column函数的使用方法 1.colu…

Duplicate column name ‘xxx_column‘

错误场景: 使用MyBatisPlus分页查询的情况下列名重复(注:select查询不报错, 映射正常) 例如 → select id, name, name from user 解决方法: 列名重复,删除重复的列名, 保证留一个就可以了 错误原因: 根据错误定位到PaginationInterceptor的queryTotal方法 最终…

mysql插入报错:colum xxx cannot be null

测试同学催促我赶紧解决上面的问题,首先看了下数据库这个字段确实是必填的,默认是当前时间 可是看了下代码发现mybatis的sql语句插入的时候包含了这个operate_time字段 那么讲道理必需给实体对象的operateTime字段赋值才行,可线上代码明明没有…

Vue template中函数获取el-table-colum中的属性值

方案如下&#xff1a; <el-table-column prop"id" label"操作"><template slot-scope"scope"><istyle"margin: 0 10px; cursor: pointer"click"clickItemInfo(scope.$index, scope.row,scope.column,scope.row.i…

hbase架构原理之region、memstore、hfile、hlog、columm-family、colum、cell

**鄙人的新书《elasticsearch7完全开发指南》&#xff0c;欢迎订阅&#xff01;** ----- https://wenku.baidu.com/view/8ff2ce94591b6bd97f192279168884868762b8e7 **《kibana权威指南》** ---- https://wenku.baidu.com/view/24cfee1ce43a580216fc700abb68a98270feac21 Hbas…

Row Column

Row Column 参考&#xff1a; Row classFlutter Layout Cheat SheetFlutter — Row/Column Cheat Sheet mainAxisAlignment和crossAxisAlignment 属性mainAxisAlignment和crossAxisAlignment mainAxisAlignment - 表示的是主轴的对齐方式crossAxisAlignment - 表示的是次轴…

Mybatis中resultMap的Colum和property属性

1&#xff1a; resultMap标签 当我们的数据库字段与实体类的属性不一致时&#xff0c;就需要使用该标签进行一一映射。 2&#xff1a;使用情况 2.1 简单查询 <resultMap id"这个resultMap的id" type"对应实体类的全限定类名"><id column"…

CSS3多列布局columns相关属性

tip&#xff1a;有问题或者需要大厂内推的我脉脉哦&#xff1a;丛培森 ٩( ‘ω’ )و CSS3中增加了可以实现多列布局的属性 在此之前的实现很麻烦可能需要各种定位 现在我们只需要一个属性就可以实现 多列布局类似于我们的报纸布局 这样可以方便读者观看 #多列数量与多列宽度#…

mysql5.7以上报错:Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated colum

这里写目录标题 一、前言二、解决方法临时解决&#xff1a;永久解决&#xff1a; 一、前言 在写sql时报错信息&#xff1a; 1055 - Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘pms.ru.role_id’ which is not functionall…

Vue+EleMentUI实现el-table-colum表格select下拉框可编辑

说明&#xff1a; 在进行采购入库的过程中&#xff0c;有必要对表格中的一行进行快速编辑保存&#xff0c;节省时间&#xff0c;提高工作效率&#xff01;&#xff0c;而不是每次编辑都要弹窗才可编辑 源码&#xff1a;https://gitee.com/charlinchenlin/store-pos 效果图&am…

Flutter学习(三)Row,Colum布局

主题 本文将介绍&#xff0c;flutter中的row&#xff0c;colum的用法。通俗来说&#xff0c;就是横向布局和纵向布局的用法。 开发环境 win10 androidstudio2022.1.1 jdk11 fluttersdk-flutter_windows_3.7.8 源码 文末将会附上完整开源demo地址 开发过程 首先&#xff…

column多列布局

CSS3 新增多列布局适合排版很长的文字内容&#xff0c;让其多列显示。使开发者能够轻松实现报纸版式的布局。 colum的相关属性&#xff1a; 属性说明column-count属性值是一个数字&#xff0c;规定元素被分为几列column-width列宽column-gap列与列的间隔宽度column-rule列的间…

为什么函数f(x)=x²不是满射

看到许多同学在问这个问题&#xff0c;一时也不知道该问谁&#xff0c;今天就去刨根问底了一下。 大致弄清缘由了&#xff0c;很可能是有同学看到有一本书《高等数学第7版上册》&#xff08;同济大学数学系 编&#xff09;&#xff0c;其中的第一章 函数与极限 第2页 例1提到&…

e^x导数证明

证明当x→0时,e^x-1与x是等价无穷小 https://www.zybang.com/question/1888f36ace3f205309482870c58e8a64.html