Java JNA调用C函数常见问题及解决方法

目录

  • 1 undefined symbol:xxx
  • 2 Java映射C数组乱码
  • 3 Java使用String接收不到C函数返回的char*
  • 4 Unable to load DLL 'xxx.dll'
  • 5 java.lang.UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序
  • 6 无效的ELF头
  • 7 Structure array elements must use contiguous memory
  • 8 java.lang.IndexOutOfBoundsException

以下是博主自己使用JNA过程中遇到的一些问题汇总,分享给大家,少踩坑。

1 undefined symbol:xxx

在这里插入图片描述
在so中找不到指定的符号,往往是因为函数在so中没有定义导致的。
解决方法:检查C中函数是否正确定义。

2 Java映射C数组乱码

直接使用getBytes传参乱码
在这里插入图片描述

typedef struct
{int enable;char static_ip[20];char netmask[20];char gateway[20];char dns1[20];char dns2[20];
} network_eth;extern "C"{int sdk_set_network_eth(const char* ip, network_eth* network_param);
}
//函数定义
int sdk_set_network_eth(const char *ip, network_eth *network_param){if (strlen(ip) == 0 || network_param == NULL){printf("sdk_set_network_eth param error!\n");return -1;}printf("ip:%s\n",ip);printf("network_eth enable:%d\n",network_param->enable);printf("network_eth static_ip:%s\n",network_param->static_ip);printf("network_eth netmask:%s\n",network_param->netmask);printf("network_eth gateway:%s\n",network_param->gateway);printf("network_eth dns1:%s\n",network_param->dns1);printf("network_eth dns2:%s\n",network_param->dns2);return 0;
}

Java模拟结构体:

public class NetWorkEth extends Structure {
// 成员变量声明,与C结构体中声明的变量顺序一一对应
public int enable;
public byte[] static_ip = new byte[20];
public byte[] netmask = new byte[20];
public byte[] gateway = new byte[20];
public byte[] dns1 = new byte[20];
public byte[] dns2 = new byte[20];// 接口类声明
public static class ByReference extends NetWorkEth implements Structure.ByReference{}
public static class ByValue extends NetWorkEth implements Structure.ByValue{}/**
* 定义取值次序,需要与c中对齐,不然会报NoSuchFieldError
* @return
*/
@Override
protected List getFieldOrder(){return Arrays.asList(new String[] {"enable", "static_ip", "netmask", "gateway", "dns1", "dns2"});}
}// 测试C函数
@Test
public void NetworkTest(){NetWorkEth.ByReference nwbr = new NetWorkEth.ByReference();String ip = "0.0.0.0";int res = CLibrary.INSTANCE.sdk_set_network_eth(ip,null);log.error("res="+res);Assert.assertEquals(-1,res);nwbr.enable = 1;// 错误用法
//        nwbr.static_ip = "10.20.6.10".getBytes() ;
//        nwbr.netmask = "255.255.255.0".getBytes();
//        nwbr.gateway = "192.168.122.134".getBytes();
//        nwbr.dns1 = "114.114.114.114".getBytes();
//        nwbr.dns2 = "8.8.8.8".getBytes();// 正确用法nwbr.static_ip = Arrays.copyOf("10.20.6.10".getBytes(),20);nwbr.netmask = Arrays.copyOf("255.255.255.0".getBytes(),20);nwbr.gateway = Arrays.copyOf("192.168.122.134".getBytes(),20);nwbr.dns1 = Arrays.copyOf("114.114.114.114".getBytes(),20);nwbr.dns2 = Arrays.copyOf("8.8.8.8".getBytes(),20);res = CLibrary.INSTANCE.sdk_set_network_eth(ip,nwbr);Assert.assertEquals(0,res);}

乱码原因:
        一开始以为C++和Java的数组类型都是一样的,直接用C++的char[]对应Java的byte[],但是发现错误,不可行,查找资料发现C++的数组类型在内存中是连续存储的,而Java的数组不一定是连续的。对C中的char数组类型赋值时,不能直接给数组赋值,要使用Arrays.copyOf(String.getBytes(),20)赋值,数组长度和C结构体中声明的长度保持一致。
        在某些情况下,虽然使用String.getBytes()转换也能成功,但大多数情况下,使用该方法会出现乱码,不建议使用String.getBytes()。推荐使用Arrays.copyOf()。
解决方法:
使用使用Arrays.copyOf()

3 Java使用String接收不到C函数返回的char*

JNA使用String无法直接接收C 函数返回类型为char*的值,必须要用Pointer进行接收。
【注意】当C函数的参数为char*、const char*用做输入时,JNA可以使用String类型进行传参,此时可以正常调用C函数;
但当C函数的参数类型为char*且用作输出时,使用String类型无法正常接收,必须使用Pointer进行处理。

假设有下面的函数:int sdk_temp_buf_get(char* databuf,const char* ip);
函数接收一个不为空且ip为指定内容的主机地址,返回一个温度值保存在databuf中
【实例】使用String接收char*返回结果
在这里插入图片描述
解决方法: 使用Pointer接收char*类型的返回值
在这里插入图片描述

4 Unable to load DLL ‘xxx.dll’

产生原因:
动态库和jdk位数不匹配
64位的jdk只能调用64位的dll,32位也一样。如果使用的jdk和dll位数不同,会报Unable to load DLL ‘xxx.dll’
解决方法:
确保动态库和jdk的位数相同,32位的so就用32位的jdk,64位so就用64位jdk。

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

产生原因:
动态库类型和系统类型不匹配,多是由于在windows下调用了Linux下的so。如果排除了这个原因,则是动态库和jdk位数不匹配,
64位的jdk只能调用64位的dll,32位也一样。
解决方法:
确保动态库类型和系统类型匹配,windows下调用dll,Linux下调用so;确保动态库和jdk的位数相同。

6 无效的ELF头

windows系统下的动态库后缀名为.dll,Linux下的动态库后缀名为.so。
不能在windows系统上调用.so库中的函数,同样也不能在Linux系统上调用.dll文件。
Linux下调用.dll报错:无效的ELF头
解决方法:确保动态库类型和系统类型匹配

7 Structure array elements must use contiguous memory

这个报错意思是结构数组元素必须使用连续内存,一般发生在用结构体数组做参数时,传参直接new了对象赋值给数组。
看下面一个例子:
Java接口声明:int changeObjs(Structure per[], int size);
Person[] per = new Person[2];
Person p1 = new Person();
Person p2 = new Person();
p1.age = 1;
p1.name = Arrays.copyOf(“k1”.getBytes(),20);
p2.age = 2;
p2.name = Arrays.copyOf(“k2”.getBytes(),20);
per[0] = p1;
per[1] = p2;
结构体数组必须使用连续的内存区域。p1,p2都是new出来的对象,不可能连续,用传统方式初始化数组不能解决。
解决方法:使用JNA的toArray产生内存连续的结构体数组

Person pb = new Person();
Person[] pers = (Person[]) pb.toArray(2);
pers[0].age = 1;
pers[0].name = Arrays.copyOf("k1".getBytes(),20);
pers[1].age = 2;
pers[1].name = Arrays.copyOf("k2".getBytes(),20);
CLibrary.INSTANCE.changeObjs(pers, 2);

8 java.lang.IndexOutOfBoundsException

原因:在结构体数组做参数时,Java接口声明中错误把参数类型写成Person.ByValue
解决方法:将参数类型改为结构体本身即可
即不带ByReference或ByValue。结构体数组做参数时,要区别于非数组的ByReference和ByValue。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/408026.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

msvcp120.dll丢失是怎么回事?几种靠谱修复msvcp120.dll的方法

在使用基于Windows的计算机进行日常工作或娱乐时,您可能会遇到一个错误消息:“无法启动此程序,因为计算机中丢失msvcp120.dll。”这样的提示通常在尝试启动某些程序或游戏时弹出,导致应用无法正常运行。这个问题通常与系统中的某个…

CSS3页面布局-三栏-固定宽度布局

布局的基本概念 多栏布局三种基本实现方案:固定宽度,流动,弹性。 固定宽度布局:大小不会随用户调整浏览器窗口大小。 一版960-1100,960常见,可以被3,4,5,6,8,10,12,16整除。 流动布局:大小会随用户调整…

数据结构——链式二叉树的实现与分治编程思维(c语言实现)

目录 前言: 1.前置说明 2.链式二叉树的遍历 2.1 前序,中序及后续遍历 2.2 前序遍历实现 2.3 中序遍历实现 2.4 后续遍历实现 3.结点个数以及高度等 3.1 结点个数 3.2 结点高度 3.3 叶子结点的个数 前言: 在之前的学习中&…

【图解秒杀系列】秒杀技术点——多级缓存、分层过滤

【图解秒杀系列】秒杀技术点——多级缓存、分层过滤 多级缓存本地缓存分布式缓存 分层过滤 多级缓存 多级缓存在秒杀系统中是非常重要的一个技术点,是应对秒杀场景瞬时高并发读请求的一种有效手段。通过在数据库前面加入多个缓存层,达到过滤掉大多数读请…

优惠券秒杀项目

一、添加优惠券的同时,将优惠券信息,以及用户列表放到redis中 Override Transactional public void addSeckillVoucher(Voucher voucher) {// 保存优惠券save(voucher);// 保存秒杀信息SeckillVoucher seckillVoucher new SeckillVoucher();seckillVou…

easyexcel--多sheet页导入导出

多sheet页导出 核心代码就是下图里面的,使用EasyExcel.writeSheet创建一个sheet,然后用excelWriter写入就行了,很简单 GetMapping("downloadMultiSheet")public void downloadMultiSheet(HttpServletResponse response) throws IOException {…

【Qt】输入类控件QDateTimeEdit

目录 输入类控件QDateTimeEdit 例子:实现日期计算器 输入类控件QDateTimeEdit QDate Edit作为日期的微调框 QTime Edit作为时间的微调框 QDateTimeEdit作为时间日期的微调框 下面主要讲解QDateTimeEdit: 核心属性 属性说明 dateTime 时间⽇期的值.…

【Hot100】LeetCode—101. 对称二叉树

目录 1- 思路借助队列 2- 实现⭐101. 对称二叉树——题解思路 3- ACM 实现 原题连接&#xff1a;101. 对称二叉树 1- 思路 借助队列 1- 创建队列&#xff1a;Queue<TreeNode> queue&#xff0c;初始化加入 root.left 和 root.right2- 判断逻辑&#xff1a;while(!queu…

软件开发者的首选:最佳Bug测试工具Top 10

本篇文章介绍了以下软件bug测试管理工具&#xff1a;PingCode、Worktile、Test360、禅道、码云Gitee、优云测试、Jira、GitHub、Axosoft、Bugzilla。 在开发过程中&#xff0c;Bug的管理往往是最让人头疼的问题之一。小问题积累起来不仅会拖延项目进度&#xff0c;还可能影响到…

如何优雅处理异步组件加载:Vue 3 的 Suspense 特性

在日常开发中&#xff0c;我们可能会遇到网络不佳或内容加载时间较长的情况。如果当前页面没有任何内容提示&#xff0c;用户的体验非常糟糕&#xff0c;可能会反复刷新以便加载成功。因此&#xff0c;我们需要给用户提供一个加载中的效果&#xff0c;告知用户“我在努力加载中…

基于单片机的人体健康监测系统的设计

本设计以STM32F103C8T6单片机作为主控&#xff0c;通过MAX30102采集心率、血氧值&#xff0c;通过MSP20血压采集模块检测血压值&#xff0c;通过MLX90614红外体温采集模块检测体温值。OLED屏可以显示以上检测的信息&#xff0c;并可以通过蓝牙模块将信息发送给手机APP。当检测值…

利用VirtualBox安装CentOS系统

博主这次用VirtualBox虚拟机安装CentOS系统。无论是大小型项目都是要发布到云主机上面&#xff0c;必然要用到Linux系统&#xff0c;有的人的本地电脑硬件配置不高&#xff0c;没有办法运行数据库集群&#xff0c;所以只能借助云主机。毕竟云主机也是Linux系统&#xff0c;大家…

大数据-92 Spark 集群 SparkRDD 原理 Standalone详解 ShuffleV1V2详解 RDD编程优化

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

OZON什么产品好卖丨OZON婴儿用具产品

Top1 摇铃 Деревянная стойка тренажер Монтессори для мобилей и игрушек для новорожденных / развивающая дуга 商品id&#xff1a;1557614414 月销量&#xff1a;707 OZON婴儿用具…

Leetcode-day31-01背包问题

46. 携带研究材料 1.dp数组代表的是什么&#xff1f; 这里的dp数组是一个二维数组&#xff0c;dp[i][j]是从前i个物品中任选放入容量j内的最大价值。 2.递推公式。 不放物品i&#xff1a;由dp[i - 1][j]推出&#xff0c;即背包容量为j&#xff0c;里面不放物品i的最大价值&am…

uniapp检测手机是否打开定位权限Vue3-直接复制粘贴

安卓示例&#xff1a; 苹果示例&#xff1a; 代码实现&#xff08;vue3写法&#xff09;&#xff1a; const checkGPS ()>{console.log(开始监听GPS状态);let system uni.getSystemInfoSync(); // 获取系统信息if (system.platform android) { // 判断平台var context …

全国上市公司网络安全风险指数(2001-2023年)

数据来源&#xff1a;本数据参考耿勇老师等&#xff08;2024&#xff09;做法采集了2001-2023年的上市公司年报&#xff0c;所有年报均来自于深交所和上交所官方网站&#xff0c;通过对上市公司的年报进行精读&#xff0c;提取出包括网络安全、网络攻击等在内的39个关键词构成企…

牛客笔试小题

目录 牛客.小红取数 牛客.哈夫曼编码​编辑 牛客.字符编码(上一道题的资料) 牛客.最小的完全平方数 牛客.小红取数 01背包问题:在满足总和必须为k的倍数的情况下&#xff0c;选择最大的总和 1.状态表示: dp[i][j]:表示从前面i个数字中挑选&#xff0c;总和%k等于j时候,最大的…

微服务——远程调用

为什么需要远程调用&#xff1f; 在微服务架构中&#xff0c;每个服务都是独立部署和运行的&#xff0c;它们之间需要相互协作以完成复杂的业务逻辑。因此&#xff0c;远程调用成为微服务之间通信的主要方式。通过远程调用&#xff0c;一个服务可以请求另一个服务执行某些操作或…

数学建模国赛获奖技巧

一、团队分工合作的技巧&#xff08;三角形配合&#xff09; &#xff08;1&#xff09;队长要组织多沟通多交流&#xff1b; &#xff08;2&#xff09;建议定期开组会&#xff0c;互相讲授自己学习的东西&#xff0c;一人学习&#xff0c;三人收获。 二、AI辅助思路解析&am…