系统编程后端【免费下载链接】jnaJava Native Access项目地址https://gitcode.com/gh_mirrors/jn/jna点击查看免费下载导读本文基于 www/Mappings.md 展开系统讲解 JNAJava Native Access中 Java 类型与原生 C 类型的默认映射规则从基础类型对照表、平台相关的尺寸差异如long、wchar_t到NativeLong等适配类型的底层实现再到通过TypeMapper、NativeMapped定制映射的高级用法。读完本文你将能准确为任何 C 函数接口选择对应的 Java 类型并能用自定义映射解决 BOOL、stdcall 命名等平台兼容问题。一、核心原则等宽映射Java primitive types (and their object equivalents) map directly to the native C type of the same size.JNA 默认映射的第一条原则是Java 原始类型及其包装类型直接映射到同尺寸的原生 C 类型。也就是说JNA 不是按“语义”而是按“位宽”来建立对应关系——只要 Java 类型与 C 类型的字节数一致就可以直接对应。这条原则的源码依据可以在 Native.getNativeSize(Class) 中看到JNA 为每个 Java 类维护一张“原生尺寸表”例如byte→1 字节、short→2 字节、int→4 字节、long→8 字节等调用前的参数装箱、返回值解包都依赖这张表。值得注意的是源码中boolean/Boolean的默认原生尺寸被硬编码为4 字节即按 32 位整数处理这正对应下表中int → boolean → BOOL的映射。二、默认类型映射对照表下表来自 www/Mappings.md列出了 JNA 默认的 Java ↔ Native 类型映射关系Native TypeSizeJava TypeCommon Windows Typeschar8-bit integerbyteBYTE, TCHARshort16-bit integershortWORDwchar_t16/32-bit charactercharTCHARint32-bit integerintDWORDintboolean valuebooleanBOOLlong32/64-bit integerNativeLongLONGlong long64-bit integerlong__int64float32-bit FPfloatdouble64-bit FPdoublechar*C stringStringLPCSTRvoid*pointerPointerLPVOID, HANDLE, LPXXX原文档还给出了两条补充规则无符号类型使用与有符号类型相同的映射例如 C 的unsigned int依然对应 Java 的intunsigned short对应short位宽不变即可C 枚举通常可与int互换枚举成员在底层就是整数值JNA 接口中直接使用int或自定义枚举类型皆可。三、关键映射背后的平台差异3.1wchar_t→char宽字符的尺寸分歧表中wchar_t标注为“16/32-bit character”。在 Windows 上wchar_t是 16 位对应 UTF-16 编码而在多数类 Unix 平台Linux、macOS上它是 32 位对应 UTF-32。JNA 在运行期通过原生代码探测实际尺寸Native.WCHAR_SIZE字段保存当前平台的wchar_t字节数见 Native.javagetNativeSize中char.class / Character.class返回的就是WCHAR_SIZE见 Native.java。因此JNA 的char参数/字段在 Java 侧始终是单个char在原生侧则按平台自动适配 2 或 4 字节这让跨平台接口声明保持统一。3.2long→NativeLongC long 的可变位宽C 的long在 64 位 Unix 系统上是 64 位在 WindowsLLP64 模型上却仍是 32 位。若直接用 Java 的long固定 64 位去映射Windows 上就会错位。JNA 为此专门设计了NativeLongpublic class NativeLong extends IntegerType { /** Size of a native long, in bytes. */ public static final int SIZE Native.LONG_SIZE; public NativeLong() { this(0); } public NativeLong(long value) { this(value, false); } public NativeLong(long value, boolean unsigned) { super(SIZE, value, unsigned); } }NativeLong.SIZE直接取自Native.LONG_SIZE运行期探测值见 Native.java。它的基类IntegerType实现了NativeMapped接口setValue根据size1/2/4/8做截断与符号处理toNative()返回对应的装箱数值fromNative()通过Klass.newInstance重建实例并回填值。使用示例public interface LibC extends Library { // C 原型: long lseek(int fd, long offset, int whence); NativeLong lseek(int fd, NativeLong offset, int whence); }IntegerType还支持构造时传入unsignedtrue表示无符号语义内部按0xFF/0xFFFF/0xFFFFFFFF掩码保留位模式适合处理unsigned long、unsigned int等场景。3.3void*→Pointer与char*→Stringchar*JNA 将其视为 C 字符串并自动映射为 JavaString负责编码/解码与\0终止符处理对应 Windows 的LPCSTR。若需要宽字符串可使用WString对应wchar_t*/LPCWSTR。void*不透明指针映射为PointerWindows 上的LPVOID、HANDLE以及各类LPXXX指针均属此类。从getNativeSize的实现可见Pointer、String、WString、Callback、Buffer在栈上统一按POINTER_SIZE指针宽度传递。四、深入源码默认映射如何被查找映射查找入口有两个Function方法参数与返回值与Structure结构体字段。以函数调用为例Function.java 对返回类型调用mapper.getFromNativeConverter(returnType)Function.java 对每个参数调用mapper.getToNativeConverter(type)若未配置TypeMapperJNA 走内置默认路径。TypeMapper接口定义了两个方向的方法见 TypeMapper.javapublic interface TypeMapper { FromNativeConverter getFromNativeConverter(Class? javaType); ToNativeConverter getToNativeConverter(Class? javaType); }默认实现DefaultTypeMapper维护toNativeConverters与fromNativeConverters两个注册表支持三种注册方式addToNativeConverter(cls, converter)注册 Java→Native 单向转换addFromNativeConverter(cls, converter)注册 Native→Java 单向转换addTypeConverter(cls, converter)注册双向转换。DefaultTypeMapper的getAltClass方法会自动将int.class与Integer.class、boolean.class与Boolean.class等原始类型/包装类型配对注册因此注册一次即可覆盖两种写法。查找时按注册顺序做isAssignableFrom匹配见 DefaultTypeMapper.java支持父类/接口级别的宽泛匹配。ToNativeConverter的nativeType()返回值必须是 JNA 支持的原生类型集合Pointer、Boolean、Byte、Short、Character、Integer、NativeLong、Long、Float、Double、Structure、String、WString以及Buffer/原始类型数组注意后两者不支持 Direct 映射模式见 ToNativeConverter.java。五、自定义映射的三种方式5.1 通过 TypeMapper 定制接口级映射TypeMapper 通常用于解决“整个接口统一类型转换”的需求最典型的就是Javaboolean↔ Win32BOOL32 位整数。使用方式是把映射器实例作为TYPE_MAPPER选项传给Native.loadMapString, Object options new HashMap(); options.put(Library.OPTION_TYPE_MAPPER, new W32APITypeMapper()); MyLibrary lib Native.load(mylib, MyLibrary.class, options);相关选项键定义在 Library.javaOPTION_TYPE_MAPPER type-mapper。Native.load会在加载库时读取该选项并传递给后续的函数调用见 Native.java。DefaultTypeMapper适合作为自定义映射器的基类在构造器中追加自己的转换规则。仓库中的 TypeMapperTest.java 提供了可直接运行的完整示例例如把Boolean映射成魔法值整数见 TypeMapperTest.javaDefaultTypeMapper mapper new DefaultTypeMapper(); mapper.addToNativeConverter(Boolean.class, new ToNativeConverter() { Override public Object toNative(Object arg, ToNativeContext ctx) { return Integer.valueOf(Boolean.TRUE.equals(arg) ? MAGIC : 0); } Override public Class? nativeType() { return Integer.class; } }); TestLibrary lib Native.load(testlib, TestLibrary.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper)); assertEquals(MAGIC, lib.returnInt32Argument(true));测试中还演示了双向转换Integer → Boolean见 TypeMapperTest.java、String ↔ WString转换TypeMapperTest.java以及Structure 字段级别的映射把结构体中的boolean字段映射为 4 字节整数后Structure.size()变为 4、写入内存的值变为 1/0TypeMapperTest.java。5.2 通过 NativeMapped 实现类级映射如果只有某一类特定对象需要特殊映射可以让该类型实现NativeMapped接口。它要求实现三个方法public interface NativeMapped { Object fromNative(Object nativeValue, FromNativeContext context); Object toNative(); Class? nativeType(); }NativeLong、IntegerType的子类正是走这条路。实现类必须提供无参构造器NativeMappedConverter通过反射实例化。典型的枚举映射写法public enum Status implements NativeMapped { OK(0), ERROR(-1); private final int code; Status(int code) { this.code code; } Override public Object toNative() { return code; } Override public Object fromNative(Object v, FromNativeContext c) { return valueOf(((Number) v).intValue()); } Override public Class? nativeType() { return Integer.class; } }这样接口方法签名中直接使用Status即可JNA 会经NativeMappedConverter自动完成双向转换枚举的完整用法同样可见于 TypeMapperTest.java。5.3 通过 FunctionMapper 定制函数名映射除了类型映射JNA 还允许定制Java 方法名 → 原生函数名的映射对应选项键OPTION_FUNCTION_MAPPER function-mapper见 Library.java。典型实现是 Windows 平台的StdCallFunctionMapperstdcall 约定要求导出函数名带有字节数后缀该实现会计算每个参数的原生栈尺寸并拼出形如FuncName12的装饰名找不到时再尝试带下划线的_FuncName12最后回退到未装饰名见 StdCallFunctionMapper.java。MapString, Object options new HashMap(); options.put(Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionMapper()); MyWin32Lib lib Native.load(user32, MyWin32Lib.class, options);需要留意若同时使用了自定义类型映射getArgumentNativeStackSize会根据NativeMapped的实际原生类型推算栈大小对于原生类型尺寸未知的自定义类可通过覆写该方法补充见 StdCallFunctionMapper.java。六、实践建议与常见误区long别用 Javalong直连除非你明确目标平台是 64 位 Unix此时long恰好 64 位跨平台代码应统一使用NativeLong否则 Windows 上会栈错位boolean默认是 4 字节整数getNativeSize中boolean/Boolean硬编码为 4C 头文件里的BOOL就按此处理若是 C99 的_Bool1 字节需要自定义映射char不等同于 1 字节JNA 的char按wchar_t尺寸2 或 4 字节处理映射 C 的 8 位char应使用byte映射器顺序敏感DefaultTypeMapper按注册顺序查找先注册的转换器优先命中注册宽泛类型如CharSequence时要放在具体类型之后无符号类型用同尺寸有符号类型承接仅当需要访问无符号位模式时才考虑IntegerType(..., true)等带unsigned标志的包装。七、进一步阅读默认映射总表原文档www/Mappings.md自定义映射官方说明www/CustomMappings.md映射器接口与默认实现TypeMapper.java、DefaultTypeMapper.java、NativeMapped.java平台尺寸探测与原生尺寸表Native.java可运行测试样例TypeMapperTest.javastdcall 函数名映射器StdCallFunctionMapper.java赞分享系统编程后端【免费下载链接】jnaJava Native Access项目地址https://gitcode.com/gh_mirrors/jn/jna点击查看免费下载相关推荐BLOOM-3B模型深度解析30亿参数如何实现45种自然语言与12种编程语言支持 BLOOM 3B模型深度解析30亿参数如何实现45种自然语言与12种编程语言支持 想要了解如何用30亿参数的AI模型支持45种自然语言和12种编程语言吗PyO3 类型转换对照表全解析Rust 类型与 Python 类型的一一映射PyO3 类型转换对照表全解析Rust 类型与 Python 类型的一一映射 导读 在 PyO3 中编写可被 Python 调用的函数 pyfunctio开发工具TypeGraphQL类型转换自定义类型映射规则TypeGraphQL类型转换自定义类型映射规则 TypeGraphQL通过类型映射机制实现TypeScript类型与GraphQL标量 Scalar 的转换后端GraphQLAPI设计上一篇Docker垃圾清理终极指南12个环境变量全面掌握配置技巧下一篇ODS本地STT实战Whisper语音识别私有化部署完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
Agent-Reach 更新日志深度解读:从版本演进看多渠道接入、登录态判定与反爬对抗的工程实践 人工智能AI AgentMCP 服务AI 技能CLI 【免费下载链接】Agent-Reach 给你的 AI Agent 一键装上互联网能力。13 个平台(网页/GitHub/YouTube/小红书/B站/Twitter/Reddit 等)多后端路由,当下最稳的接入方式替你选好、装好、体检好。GitHub 主仓库… · 2026/9/25 3:13:12
15个真实业务AI Agent项目:从能跑通到敢上线 1. 这不是“又一个Agent教程”,而是我用37个真实业务场景筛出来的15个必练项目你点开这个标题,大概率是因为最近投简历时被卡在了“熟悉AI Agent开发”这一栏——不是没学过LangChain、不是没跑通过Hello World,而是面试官问“你做过什么能体… · 2026/9/25 3:13:12
AutoClicker配置持久化与日志机制详解:System.Text.Json与Serilog完整实现走读 AutoClicker配置持久化与日志机制详解:System.Text.Json与Serilog完整实现走读 【免费下载链接】AutoClicker AutoClicker is a useful simple tool for automating mouse clicks. 项目地址: https://gitcode.com/gh_mirrors/au/AutoClicker
AutoClicker 是一… · 2026/9/25 3:13:05
GEO全场景智能生态:全栈隐私计算与绿色低碳规模化落地实践 GEO这个缩写,去年在圈内还属于小范围讨论的概念,今年已经高频出现在各类招标书和企业战略PPT里。从热搜词的密集程度就能感受到风向的变化:GEO优化、GEO服务商、GEO投毒攻击、GEO数据结构、GEO招标项目……说明大量企业已经越过“要不要做GEO… · 2026/9/25 3:45:38
基于Spring Boot的美食推荐系统实战:协同过滤与部署全解析 民以食为天,但"吃什么"这个问题,每天都要消耗大量决策时间。2023年我做了一个基于Spring Boot的美食推荐系统,初衷很简单:不想再让用户面对几百道菜翻来翻去无从下手,而是根据每个人的口味偏好、历史行为&am… · 2026/9/25 3:45:38
基于SVM的降水量预测模型实战:SVR回归、特征构造与调参要点 简介:一套基于支持向量机(SVM)的降水量预测模型代码包,面向机器学习、人工智能及数据挖掘方向的初学者和研究人员,可用于算法复现、实验对比和毕业设计参考。资源内共 54 个文件,以 26 个 .m 主程序为核心&… · 2026/9/25 3:45:38
5个可落地的免费AI Agent工作流实战指南 1. 这不是工具清单,而是一套可落地的“时间置换系统” “5个免费AI Agent,让我每天省出3小时”——这句话乍看像标题党,但背后藏着一个被多数人忽略的事实:我们真正缺的从来不是工具,而是把AI从“玩具”变成“同事”的… · 2026/9/25 3:45:38
Spring Boot酒店客房管理系统:源码+论文打造完整毕设 简介:酒店客房管理系统毕业设计资料,包含完整源码与论文,面向Java Web课程设计或毕设开发人员,同时也适合需要搭建酒店管理场景的初学者。系统覆盖客房信息管理、客房清扫管理、用户入住管理、会员管理、收藏客房等核心业务&#… · 2026/9/25 3:45:32
STM32F107+LAN8720A以太网调试指南:从CubeMX到LWIP完整流程 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 3:45:26
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37