当前位置: 首页 > news >正文

Java 使用Jna 调用 C# dll文件踩到的坑

Java 使用Jna 调用 C# dll文件踩到的坑

背景: java需要调用一个GSmart_C_x64.dll中的PhyValDecode方法
传参是:

extern static PhyVal PhyValDecode(byte head, byte sensor, byte[] rawdata);

返回实体类为

public struct PhyVal
{
public float Temperature;
public float acc_X; 
public float acc_Y; 
public float acc_Z; 
public float ang_X;
public float ang_Y;
public float ang_Z;
};

坑1

报错: Unsupported return type class com.valeo.jna.PhyVal$ByValue in function PhyValDecode
原因: 没有继承Structure, 没有重写
@Override
protected List getFieldOrder()

坑2

报错: invalid memory access
这个问题, 我看到有很多网友都发了, 但引发这个问题的有很多种原因
原因1: 返回参数的实体类没有实现Structure.ByValue 这个代码

// 必须定义此内部类,否则JNA可能无法正确实例化public static class ByValue extends PhyVal implements Structure.ByValue {}

那你实现了这个代码之后, 一定要记得引用
我在我的返回实体类出参interface是这样写的PhyVal.ByValue

public interface VTSSDK2 extends Library {VTSSDK2 INSTANCE = Native.load("VTS_GSmart_C_x64.dll", VTSSDK2.class);PhyVal.ByValue PhyValDecode(byte head,byte sensor, Pointer rawData);
}

坑3

报错: invalid memory access
这个是传参问题, 我上面说的是入参问题
C#的传参是
extern static PhyVal PhyValDecode(byte head, byte sensor, byte[] rawdata);
但我这样调用

PhyVal.ByValue PhyValDecode(byte head,byte sensor,byte[] rawData);

依旧报错invalid memory access, 后面问了AI , AI建议我使用Pointer这个类
import com.sun.jna.Pointer;
使用了这个类之后就OK了, 后面查询原因可能是因为

byte[] 导致内存溢出的原因
当 JNA 调用原生函数(如 DLL 中的函数)并传递 byte[] 时,会执行以下操作:自动分配原生内存:JNA 会在原生内存(非 JVM 堆内存)中分配一块与 byte[] 长度相同的缓冲区。
数据复制:将 Java 中 byte[] 的内容完整复制到这块原生内存中。
自动释放:函数调用结束后,JNA 会自动释放这块原生内存。如果出现内存溢出,通常是因为:数组过大:如果 byte[] 长度非常大(例如几 MB 甚至 GB),JNA 分配的原生内存块会占用大量原生内存,超过系统限制时就会溢出。
频繁分配:如果频繁调用该函数(例如在循环中),JNA 会频繁分配和释放原生内存,可能导致原生内存碎片或分配不及时,引发溢出。
函数对内存的特殊要求:如果原生函数期望的是一块预分配的、更大的内存(例如函数内部会向指针写入超过 byte[] 长度的数据),byte[] 的固定长度会导致写入越界,表现为内存溢出(本质是缓冲区溢出)。Pointer 不报错的原因
Pointer 是对原生内存地址的直接引用,不涉及自动内存分配和复制,具体行为如下:不自动分配内存:Pointer 本身只是一个地址标识,需要你手动分配原生内存(通常通过 new Memory(size) 实现,Memory 是 Pointer 的子类)。
无数据复制:如果 Pointer 指向的是你预先分配的 Memory,Java 数据写入 Memory 时是直接操作原生内存,无需额外复制。
灵活控制内存大小:你可以根据原生函数的实际需求,分配足够大的 Memory(例如 new Memory(1024 * 1024) 分配 1MB 内存),避免缓冲区溢出。

那这里我在写一个Point的使用示例:

Pointer dataPointer = new com.sun.jna.Memory(dataWithoutEnd.length);
dataPointer.write(0, dataWithoutEnd, 0, dataWithoutEnd.length);

坑4 这里我在说一下dll的引用问题, 我是这样引用的

在这里插入图片描述

http://www.dtcms.com/a/353664.html

相关文章:

  • SpringBoot整合Redis:从入门到实战的完整指南
  • 【Linux 小实战】自定义 Shell 的编写
  • LCD 上显示字符
  • zookeeper-集群扩缩容
  • 稳敏双态融合架构--架构师的练就
  • banner这个文件是怎么请求到后端数据的
  • Rust:引用
  • Vue-24-利用Vue3的element-plus库实现树形结构数据展示
  • Autodesk Maya 2026.2 全新功能详解:MotionMaker AI 动画、LookdevX 材质增强、USD 工作流优化
  • 在MiniOB源码中学习使用Flex与Bison解析SQL语句-第二节
  • 【Linux】正则表达式学习记录
  • FFMPEG api使用
  • 从disable_cost到disabled_nodes,最小代价预估质的飞跃
  • nestjs日志(nest-winston)
  • pyecharts可视化图表-tree:从入门到精通
  • Linux 系统调优与CPU-IO-网络内核参数调优
  • Task04: CAMEL框架中的多智能体系统(课程第三章剩余章节)
  • 大模型安全概述、LlamaFirewall
  • ESP8266:Arduino学习
  • 前端性能优化:从指标监控到全链路落地(2024最新实战指南)
  • 短视频矩阵管理软件推荐——小麦矩阵系统深度解析
  • 关于两视图相机几何关系
  • DevExpress WPF中文教程:如何将WPF数据网格绑定到本地集合?
  • 软件定义汽车(SDV)调试——如何做到 适配软件定义汽车(SDV)?(下)
  • vue新能源汽车销售平台的设计与实现(代码+数据库+LW)
  • 【Vue2✨】 Vue2 入门之旅(二):模板语法
  • Python异步编程:从理论到实战的完整指南
  • Qt---项目架构解读
  • BiLSTM-Attention分类预测+SHAP分析+特征依赖图!深度学习可解释分析,Matlab代码实现
  • 【GaussDB】深度解析:创建存储过程卡死且无法Kill会话的疑难排查