系统编程后端【免费下载链接】jnaJava Native Access项目地址https://gitcode.com/gh_mirrors/jn/jna点击查看免费下载导读Java Native AccessJNA默认提供了一套 Java 与 C 原生类型之间的映射规则但真实世界的原生库往往有自己约定的方言例如 Win32 API 的BOOL是 32 位整数、stdcall 导出符号带有栈字节数后缀、某些 C 头文件通过宏把函数改名导出。本篇指南以仓库文档 CustomMappings.md 为主线系统讲解 JNA 提供的三套自定义映射机制——TypeMapper类型映射、NativeMapped类级映射与FunctionMapper函数名映射并结合 src/com/sun/jna 下的源码实现与 TypeMapperTest.java 测试用例给出可直接落地的配置代码。读完本文你将能够为任意 Java 类型定制与原生类型之间的双向转换并为 Java 接口方法定制对应的原生导出符号名。一、三大定制入口一览TypeMapper类及相关的FromNativeConverter/ToNativeConverter接口用于将任意 Java 类型作为参数、返回值或结构体成员转换为原生类型或从原生类型转换回来。FunctionMapper则负责把 Java 方法名映射到真正的原生函数名。三者分别通过Native.load的 options map 中两个键注入选项键常量定义作用type-mapperLibrary.OPTION_TYPE_MAPPER提供 Java 类型与原生类型的双向转换器function-mapperLibrary.OPTION_FUNCTION_MAPPER提供 Java 方法名到原生函数名的映射Library接口还定义了OPTION_INVOCATION_MAPPERinvocation-mapper、OPTION_STRUCTURE_ALIGNMENTstructure-alignment等选项键本文聚焦前两个映射键。options map 的基本用法如下MapString, Object options new HashMapString, Object(); options.put(Library.OPTION_TYPE_MAPPER, myTypeMapper); options.put(Library.OPTION_FUNCTION_MAPPER, myFunctionMapper); MyLibrary lib Native.load(mylib, MyLibrary.class, options);需要说明的是接口内部的 options 会自动传播到该接口内定义的结构体前提是在实例化这些结构体之前完成Native.load因此 TypeMapper 同样会影响Structure字段的读写映射。二、TypeMapper按 Java 类型注册转换器2.1 接口定义TypeMapper.java 是转换器的查询入口只声明两个方法public interface TypeMapper { FromNativeConverter getFromNativeConverter(Class? javaType); ToNativeConverter getToNativeConverter(Class? javaType); }JNA 在调用原生函数时会以参数、返回值、结构体字段的 Java 类型为键向 TypeMapper 查询对应的转换器getToNativeConverter把 Java 值转换为可被原生层识别的类型调用方向 Java → NativegetFromNativeConverter把原生层返回的值还原为 Java 类型调用方向 Native → Java。2.2 DefaultTypeMapper开箱即用的实现基类直接实现TypeMapper需要自行管理查询逻辑实践中通常继承 DefaultTypeMapper.java。它内部维护两个按注册顺序排列的转换器列表toNativeConverters与fromNativeConverters并提供三个注册方法方法说明addToNativeConverter(Class, ToNativeConverter)注册Java → 原生方向的转换器addFromNativeConverter(Class, FromNativeConverter)注册原生 → Java方向的转换器addTypeConverter(Class, TypeConverter)注册双向转换器等价于同时注册两个方向DefaultTypeMapper的查找逻辑值得注意见 DefaultTypeMapper.java它按注册顺序遍历用entry.type.isAssignableFrom(javaClass)判断——即只要目标 Java 类型是已注册类型的子类型/实现类就命中该转换器。因此向CharSequence.class注册转换器后String、StringBuilder等参数都会被匹配这一点被 TypeMapperTest.testCharSequenceToIntArgumentConversion 验证。另一个实用细节DefaultTypeMapper通过getAltClassDefaultTypeMapper.java自动为注册的基础类型登记其包装类型以及反向。例如注册Boolean.class时boolean.class也会自动生效反之亦然无需重复注册。2.3 转换器接口ToNativeConverter / FromNativeConverter / TypeConverter转换器在原生方向必须把 Java 值转换到 JNA 支持的原生类型列表中的一种。ToNativeConverter的 javadocToNativeConverter.java明确列出了合法目标类型Pointer、Boolean、Byte、Short、Character、Integer、NativeLong、Long、Float、DoubleStructure、String、WStringjava.nio.Buffer与基本类型数组注意这两类在直接映射Direct Mapping模式下不支持。ToNativeConverter需要实现两个方法public interface ToNativeConverter { Object toNative(Object value, ToNativeContext context); // 返回上述原生类型之一 Class? nativeType(); // 声明 toNative 返回的类型 }FromNativeConverter结构对称FromNativeConverter.javapublic interface FromNativeConverter { Object fromNative(Object nativeValue, FromNativeContext context); Class? nativeType(); }TypeConverter同时继承两者适合做双向映射如布尔 ↔ 整数。nativeType()必须与toNative/fromNative实际使用的原生类型一致JNA 依赖它计算参数栈大小与返回值类型。2.4 仓库实战示例Win32 的 W32APITypeMapper文档提到Win32 API 示例接口使用类型映射器把 Java boolean 转换为 Win32 BOOL 类型其实现就是 W32APITypeMapper.java。它继承DefaultTypeMapper在构造器中注册了两类转换器布尔 ↔ BOOL32 位 inttoNative把Boolean.TRUE映射为整数1、FALSE映射为0fromNative把非零整数还原为true。注意nativeType()返回Integer.class并注释BOOL is 32-bit int——这正是文档所说把 Java boolean 转换为 Win32 BOOL的底层实现。字符串 ↔ Unicode/ASCIIUnicode 模式下String被转为WString宽字符串String[]被转为StringArray(..., true)fromNative方向则把WString的toString()还原为String。ASCII/MBCS 模式下不注册字符串转换器保留 JNA 默认的编码行为。该类的三个公开静态实例直接反映了选项用法public static final TypeMapper UNICODE new W32APITypeMapper(true); public static final TypeMapper ASCII new W32APITypeMapper(false); public static final TypeMapper DEFAULT Boolean.getBoolean(w32.ascii) ? ASCII : UNICODE;即默认实例受系统属性w32.ascii控制设置该属性则选用 ASCII 映射否则使用 Unicode 映射。2.5 测试用例映射器如何被验证TypeMapperTest.java 展示了完整的端到端用法测试库为testlib。例如testBooleanToIntArgumentConversionL45-L60注册一个把Boolean转为Integer魔法值0xABEDCF23的ToNativeConverter然后断言lib.returnInt32Argument(true)返回该魔法值testIntegerToBooleanResultConversionL152-L178则同时注册双向转换验证返回值映射。testEnumConversionL249-L281展示了更贴近实战的场景用TypeConverter把枚举常量映射为int码并验证该映射在函数参数与Structure字段中同时生效——映射器通过构造器super(mapper)传入结构体mapper.addTypeConverter(Enumeration.class, converter); EnumerationTestLibrary lib Native.load(testlib, EnumerationTestLibrary.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper)); EnumerationTestLibrary.MinTestStructure struct new EnumerationTestLibrary.MinTestStructure(); struct.field Enumeration.STATUS_0; assertEquals(Enumeration.STATUS_0, lib.testStructurePointerArgument(struct).field);testStructureConversionL192-L220则直接验证了映射对结构体布局的影响把布尔字段映射为 int 后Structure的size()变为 4而非默认布尔大小并通过getPointer().getInt(0)验证写入值。三、NativeMapped类级自定义映射文档指出另一种定制方式是让用户自定义类型本身实现NativeMapped接口在类级别上决定与原生类型互转的规则。该接口位于 NativeMapped.javapublic interface NativeMapped { Object fromNative(Object nativeValue, FromNativeContext context); Object toNative(); Class? nativeType(); }实现要点依据接口 javadoc必须提供无参构造器JNA 需要实例化该类型来完成转换与结构体字段读写toNative()把当前 Java 对象转换为nativeType()声明的原生类型表示fromNative(Object, FromNativeContext)从原生值还原 Java 对象nativeType()声明使用的原生类型同样必须落在 ToNativeConverter javadoc 列出的合法类型集合内。与 TypeMapper 的差异在于作用域TypeMapper 是库级/全局注册表按类型批量生效NativeMapped是类级自包含方案每个类型自行携带映射逻辑无需在 options map 中注册。实际项目中两者常结合使用——StdCallFunctionMapper的getArgumentNativeStackSize见下文就通过NativeMappedConverter.getInstance(cls).nativeType()处理实现了NativeMapped的参数类型以正确计算其原生栈大小。四、FunctionMapper定制 Java 方法名 → 原生函数名4.1 接口与用途默认约定下 Java 方法名必须与原生函数名一致。FunctionMapper允许打破这一约定FunctionMapper.java 的 javadoc 列举了三种典型场景C 预处理器宏改名C 代码中通过宏引用一个与实际导出符号不同的名字生成链接符号与 C 代码名不一致典型即 Windowsstdcall函数导出符号带描述参数栈大小的特殊后缀如MessageBoxW16C 函数名与 Java 命名规范冲突不建议保持原名可避免混淆。接口只声明一个方法public interface FunctionMapper { String getFunctionName(NativeLibrary library, Method method); }实现类拿到已加载的NativeLibrary与被调用的Method反射信息返回最终要查找的原生函数名。与 TypeMapper 一样通过Library.OPTION_FUNCTION_MAPPER键传入Native.load的 options map。4.2 StdCallFunctionMapperstdcall 修饰名自动生成仓库中StdCallFunctionMapper位于 src/com/sun/jna/win32/StdCallFunctionMapper.java注意它在com.sun.jna.win32包而非核心包中因为该机制是 Win32 特有约定。它的核心逻辑L69-L93遍历method.getParameterTypes()用getArgumentNativeStackSize(cls)累加每个参数的原生栈字节数pop构造修饰名name pop例如MessageBoxW带 4 个指针参数时生成MessageBoxW16先尝试以 stdcall 约定StdCallLibrary.STDCALL_CONVENTION直接解析该修饰名失败则再试前导下划线版本_ decorated部分导出器会加下划线前缀仍失败则返回原名让调用方回退到未修饰名。栈大小计算逻辑封装在可覆写的getArgumentNativeStackSize(Class? cls)L47-L59中数组按指针大小Native.POINTER_SIZE计算实现了NativeMapped的类型先取其nativeType()再求原生大小其余类型通过Native.getNativeSize(cls)获取。该类 javadoc 特别提醒如果你对基础类型使用了自定义类型映射可能需要覆写该方法以保证栈字节数按自定义原生类型计算。4.3 W32APIOptions开箱即用的 Win32 选项组合仓库在 W32APIOptions.java 中把上述两套映射打包成了可直接复用的 options mapUNICODE_OPTIONSOPTION_TYPE_MAPPER W32APITypeMapper.UNICODEOPTION_FUNCTION_MAPPER W32APIFunctionMapper.UNICODE对应MessageBoxW等带W后缀的宽字符导出ASCII_OPTIONS对应 ASCII/MBCS 版本MessageBoxA等DEFAULT_OPTIONS由系统属性w32.ascii决定取用哪一套。声明 Win32 接口时直接implements W32APIOptions它继承自StdCallLibrary即可不必手动构造 options map。这正是文档所述示例接口背后的完整机制。五、选择指南与注意事项需求场景推荐机制关键点库级批量转换某类 Java 类型如全库 boolean → BOOLTypeMapper/DefaultTypeMapper在 options map 中通过OPTION_TYPE_MAPPER注入转换器需正确声明nativeType()单一自定义类型自带映射逻辑NativeMapped实现类必须有无参构造器nativeType()需落在合法原生类型集合Java 方法名 ↔ 原生导出符号不一致FunctionMapper通过OPTION_FUNCTION_MAPPER注入Win32 stdcall 场景直接用StdCallFunctionMapper同时处理 Win32 字符串宽/窄版本与 stdcall 修饰名W32APIOptionsimplements W32APIOptions即可继承UNICODE_OPTIONS/ASCII_OPTIONS其他实践要点转换器顺序敏感DefaultTypeMapper按注册顺序查找先注册的类型或更具体的父类型优先命中详见 DefaultTypeMapper.java结构与转换器协同在Native.load之后、实例化结构体之前完成映射注册options 才会自动传播到接口内定义的结构体见 Library.java原生类型边界转换目标必须是ToNativeConverterjavadoc 列出的类型java.nio.Buffer和基本类型数组在直接映射模式下不受支持验证手段仓库 TypeMapperTest.java 与 DirectTypeMapperTest.java、W32StdCallTest.java 分别覆盖了间接模式、直接模式与 stdcall 修饰名场景可作为自定义映射器的回归测试模板。六、总结JNA 的自定义映射体系可以归纳为一条主线TypeMapper 按类型注册双向转换器、NativeMapped 让类型自描述映射规则、FunctionMapper 解耦 Java 方法名与原生符号名。三者均通过Native.load的 options map 注入源码集中在 src/com/sun/jna 与 src/com/sun/jna/win32 两个包中。掌握这套机制无论是对接 Win32 API 的 BOOL/宽字符/stdcall 修饰名还是为自定义枚举、业务类型建立与 C 结构的稳定互转都能在保持 Java 侧类型安全的同时精确控制边界语义。赞分享系统编程后端【免费下载链接】jnaJava Native Access项目地址https://gitcode.com/gh_mirrors/jn/jna点击查看免费下载相关推荐终极JNA函数映射指南FunctionMapper自定义实现技巧终极JNA函数映射指南FunctionMapper自定义实现技巧 JNAJava Native Access是一款强大的Java库它允许Java程序直接系统编程后端emacs-libvterm终极指南未来路线图与新功能展望 emacs libvterm终极指南未来路线图与新功能展望 emacs libvterm是Emacs编辑器中最强大的终端模拟器之一它基于高性能的lib系统编程后端OpenVINO 前端扩展机制详解自定义算子映射指南OpenVINO 前端扩展机制详解自定义算子映射指南 前言 在深度学习模型部署过程中经常会遇到框架原生算子与推理引擎不兼容的情况。OpenVINO 提供了一人工智能推理引擎深度学习本地部署模型优化模型量化上一篇3步打造丝滑移动端底部导航Mint UI Tabbar全解析下一篇Shotcut终极快捷键自定义指南打造高效视频编辑工作流创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
RK3568 AOSP11 从 64 位降级到 32 位:内存节省30%的完整实践指南 /* 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 5:08:35
Salt SLS 模板变量完全指南:`sls`、`slspath`、`tpldir` 等上下文变量的使用与原理 运维配置管理后端 【免费下载链接】salt Software to automate the management and configuration of infrastructure and applications at scale. 项目地址: https://gitcode.com/gh_mirrors/sa/salt 点击查看 免费下载 Salt(SaltStack)在渲… · 2026/9/25 5:08:34
基于 Dataview 的 annotated 字段与任务分组查询实战:从 test-vault 示例到源码级解析 前端知识管理数据分析 【免费下载链接】obsidian-dataview A data index and query language over Markdown files, for https://obsidian.md/. 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-dataview 点击查看 免费下载 在 Obsidian 中使用 Dataview 管… · 2026/9/25 5:08:28
阅读笔记:《云计算关键领域安全指南v5》 云计算是一种运营模型和一组技术,用于通过对计算、网络、存储等资源的抽象来管理共享资源池。云计算能够实现通过网络访问可扩展且具有弹性的可共享的物理或虚拟资源池,并可按需进行自助式资源调配和管理。云可以由几乎任何计算资源组成,从处… · 2026/9/25 5:36:09
OpenShell Release Canary 实战指南:发布工件的最后一道冒烟关卡 【免费下载链接】OpenShell OpenShell is the safe, private runtime for autonomous AI agents. 项目地址: https://gitcode.com/gh_mirrors/op/OpenShell 点击查看 免费下载 OpenShell 的 Release Canary(工作流定义位于 .github/workflows/release-c… · 2026/9/25 5:36:09
Agent技能管理实战:从Prompt堆砌到结构化技能编排 做Agent开发也有小半年了,我最大的感受是:大多数人不是被模型能力卡住的,而是被“技能管理”卡住的。你让Agent做的事越多,它的行为就越不可控,Prompt越堆越长,到最后修一个bug能扯出一串连锁问题。这个项目… · 2026/9/25 5:36:09
【电路设计】常开和常闭开关/接触器 如何选? 在电路设计中经常碰见常开和常闭的开关或者接触器,本文将会简要按照我的理解说明一下常开,常闭的选择依据。常开常闭其实在正常的工况下没有什么过大的区别,但是在某些故障场景,常开和常闭就是非常重要的选择。常开:在… · 2026/9/25 5:35:56
工具调用已足够,现在基于 pkg/testing/README.md 及其源码完成文章编写。 编程语言编译器语言运行时标准库开发工具 【免费下载链接】sdk The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more. 项目地址: https://gitcode.com/gh_mirrors/sdk1/sdk 点击查看 免费下载 <output文章>
Dart S… · 2026/9/25 5:35:50
创维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