没有合适的资源?快使用搜索试试~ 我知道了~
开源项目JavaNativeAccess借鉴.pdf
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 104 浏览量
2021-12-30
17:09:27
上传
评论
收藏 29KB PDF 举报
温馨提示
试读
16页
开源项目JavaNativeAccess借鉴.pdf
资源推荐
资源详情
资源评论
用更容易的方法来调用本地代码
By Jeff Friesen, JavaWorld.com, 02/05/08
如果在 Java 程序中你使用 Java Native Interface(JNI) 来调用某个特定平台下的本地库文
件,你就会发现这个过程很单调、乏味。 Jeff Friesen 一直在介绍一个知名度很低的 Java
开源项目: Java Native Access--- 它能够避免因使用 JNI 导致的错误和乏味,同时它还能让
你通过编程的方式调用 C 语言库。
在 Java 语言没有提供必要的 APIs 的情况下,Java 程序使用 Java Native Interface (JNI)
来调用特定平台下的本地库是必要的。例如:在 Windows XP 平台中,我使用过 JNI 来调
用通用串行总线和基于 TWAIN 的扫描仪器的库; 在更古老的 Windows NT 平台中, 调用过
智能卡的库。
我按照一个基本的、乏味的流程来解决这些问题:首先,我创建一个 Java 类用来载入
JNI-friendly 库(这个库能够访问其他的库) 并且声明这个类的本地方法。 然后,在使用 JDK
中的 javah 工具为 JNI-friendly 库中的函数 --- 函数和这个类中的本地方法一一对应 ---创建一
个代理。最后,我使用 C 语言写了一个库并用 C 编译器编译了这些代码。
尽管完成这些流程并不是很困难, 但是写 C 代码是一个很缓慢的过程 ---例如: C 语言
中的字符串处理是通过指针来实现的,这会很复杂的。而且, 使用 JNI 很容易出现错误,导
致内存泄漏、很难找到程序崩溃的原因。
在 Java 开源系列的第二篇文章中, 我要介绍一个更简单、 更安全的解决方法: Todd Fast
and Timothy Wall 的 Java Native Access (JNA) 项目。JNA 能够让你在 Java 程序中调用本
地方法时避免使用 C 和 Java Native Interface 。在这篇文章中, 让我以简要的介绍 JNA
和运行示例必需的软件来开始下面的内容。然后,向你展示如何使用 JNA 将 3 个 Windows
本地库中的有用代码移植到 Java 程序中。
Get started with JNA (JNA 入门)
Java Native Access 项目 在 Java.net 上,你可以到这个网站上现在这个项目的代码和在线
帮助文档。虽然在下载有 5 个相关的 jar 文件,在本文中你仅仅需要下载其中的 jna.jar 和
example.jar 。
Jna.jar 提供基本的、 运行这些示例文件必需的 jna 运行环境。 这个 jna.jar 文件除了有 Unix 、
Linux 、Windows 和 Mac OS X 平台相关的 JNT-friendly 本地库外,还包含其他几个类包。
每一个本地库都是用来访问相对应平台下的本地方法的。
example.jar 包含了不同的示例来表明 JNA 的用途。其中的一个例子是使用 JNA 来实
现一个在不同平台下的透明视窗技术的 API 。在文章最后的示例中将要展示如何使用这个
API 修复上个月的文章关于 VerifyAge2 应用中辨认透明效果的问题。
获取本地时间( Get local time )
如果你在 Java Native Access 首页 看过 ―JNA如何入门 ‖,你就会知道一个很简单的关于调
用 Windows 平台下的 API 函数: GetSystemTime () 的 JNA 示例。这个不完整的例子只
是展示了 JNA 的基本特点。 (在例子的基础上, 我做了一个更完整的基于 Windows 的例子
来介绍 JNA )我在 Windows 平台下完善了这个例子来介绍 JNA 。
第一例子基于 Windows GetLocalTime() API 函数返回本地当前的时间和日期。和
GetSystemTime() 不同的是, 返回的时间 /日期是协调通用时间 (UTC) 格式的,GetLocalTime()
返回的时间 /日期信息的格式是根据当前时区来表示。
在一个 Java 程序中使用 JNA 调用 GetLocalTime ,你需要知道这个函数所在的 Windows
平台下的动态链接库( DLL )的名称(和可能所在的地理区域)。我们发现 GetLocalTime()
和 GetSystemTime 在同一个 DLL 文件中: kernel32.dll 。你还需要知道 GetLocalTime() 在
C 语言环境中的申明。申明如下 Listing 1 :
Listing 1. GetLocalTime 在 C 语言中的申明
typedef struct{ WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD
wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD
wMilliseconds;}SYSTEMTIME, *LPSYSTEMTIME; VOID GetLocalTime(LPSYSTEMTIME
lpst);
这个基于 C 语言的申明表明传到这个函数的参数数目和类型。在这个例子中,只有一个参
数--- 一个指向 Windows SYSTEMTIME 结构体的指针。 而且,每个结构体成员的类型是 16bit
长度的无符号整型。根据这些信息,你能够创建一个完全描述 GetLocalTime() 函数的接口,
如 Listing 2 中所示:
Listing 2. Kernel32.java
// Kernel32.java import com.sun.jna.*;import com.sun.jna.win32.*; public interface
Kernel32 extends StdCallLibrary{ public static class SYSTEMTIME extends
Structure { public short wYear; public short wMonth; public short
wDayOfWeek; public short wDay; public short wHour; public short
wMinute; public short wSecond; public short wMilliseconds; } void
GetLocalTime (SYSTEMTIME result);} Kernel32 接口( The Kernel32 interface )
因为 JNA 使用通过一个接口来访问某个库中的函数, Listing 2 表示了一个描述
GetLocalTime() 的接口。根据约定,我把接口命名为 Kernel32 是因为 GetLocalTime() 在
Windows 的 kernel32.dll 库。
这个接口必须继承 com.sun..jna.Library 接口。因为 Windows API 函数遵循 stdcall 调用协
议(stdcall calling convention ),为 Windows API 申明的接口也必须继承 com.sun.jna.win32.
StdCallLibrary 接口。因此这个接口共继承了 Library 和 com.sun.jna.win32.StdCall 两个接
口。
在前面,你已经知道了 GetLocalTime() 需要一个指向 SYSTEMTIME 结构体的指针作为它
唯一的参数。 因为 Java 不支持指针, JNA 是通过申明一个 com.sun.jna.Structure 的子类来
代替的。 根据 java 文档中抽象类的概念, 在参数环境中, Structure 相当于 C 语言的 struct* 。
一个类型映射的问题
通过比较一个 API 函数返回的整型值, 你会发现 Windows/C 语言的无符号整型和 Java 语
言的有符号整型的 JNA 类型映射是有问题的。在比较的过程中,如果你不细心,那么错误
的执行过程可能导致决定性情况。导致这种后果是因为忘记任何数值的符号位的确定是根
据:在无符号整型的情况下会被解释为正号,而在有符号整型的进制中被理解为负号的。
在 SYSTEMTIME 类中的字段和 C 结构体中的相对应的属性字段的顺序是一一对应的。保
证字段顺序的一致性是非常重要的。例如,我发现交换 wYear 和 wMonth 会导致 wYear 和
wMonth 值互换。
每个字段在 java 中是 short integer 类型的。按照 JNA 首页上 ―默认类型映射 ‖章节给出的提
示,这个 short integer 分配类型是正确。然而,我们应该知道一个重要的区别: Windows
平台下的 WORD 类型等同于 C 语言环境中的 16-bit 的无符号的 short integer ,而 java 中
short integer 是 16-bit 有符号的 short integer 。
通过 Kernel32 获取本地时间( Access the local time with Kernel32 )
JNA 首页上的 GetSystemTime() 示例已经表明必须使用预先申明的接口为本地库分配一个
实例对象。你可以通过 com.sun.jna.Native 类中静态公用方法 loadLibrary(String name,
Class interfaceClass) 来完成上述的目标。 Listing 3 所示:
剩余15页未读,继续阅读
资源评论
csh18750931974
- 粉丝: 0
- 资源: 8万+
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功