JNA 教程

JNA 教程
----------

[b]1. JNA介绍[/b]
JNA提供JAVA程序访问本地共享库(DLLs), 且不需要编写JNI或本地代码.
JNA允许使用JAVA方法调用方式来直接调用本地函数.它提供了一个动态的C语言编写的转发器,自动实现JAVA类型和C类型的映射.
JNA使用一个小型本地库存根来动态调用本地代码.开发者需要定义一个JAVA接口来描述本地库存的函数,结构.
JNA包括一个平台库. 它提供已描述好本地函数类型的一组工具接口来简化本地访问.
JNA与JNI比较, 它不需要生成DLL, JNA基于JNI技术, 简化了JAVA本地访问的过程, 但性能不如JNI.

官网
[url]http://jna.java.net/[/url]

[b]2. 包说明[/b]
JNA只有一个组件:jna.jar. 它包括本地库jnidispatch. JNA自己负责抽取与加载本地库支持文件jnidispatch, 如果没有找到, 可以通过System.loadLibrary(java.lang.String)来加载.若还没有找到, 你需要自己来安装本地共享库支持文件.
platform-specific jar: 它也包括本地库jnidispatch, 主要用于Web Start.

[b]3. 示例1[/b]
调用 C标准库函数printf.

3.1 配置CLASSPATH, 加入jna.jar
3.2 编写JAVA接口描述C标准库函数printf,并调用
3.2.1 加载本地库并映射. 加载本地库C, 定义接口CLibrary 映射本地库C.
3.2.2 类型映射
3.2.3 调用映射本地函数的JAVA方法

package com.sun.jna.examples;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

/** JNA interface 映射与用法. */
public class HelloWorld {

public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
CLibrary.class);

[u] void printf(String format, Object... args);[/u]
}

public static void main(String[] args) {
CLibrary.INSTANCE.printf("Hello, World\n");
}
}

[b]4. 不需要自己一个一个来映射本地库,JNA提供platform.jar, 它映射了大多数的标准库.[/b]

[b]5. 映射名规则:[/b]
结构:根据头文件名映射
ShlObj.h
ShlObj
函数:根据DLL文件名映射.
Advapi32.dll
Advapi32
工具类:DLL文件名+Util.
Advapi32.dll
Advapi32Util

[b]6. 同步调用与异步调用[/b]
JNA本地调用默认是异步的.要同步调用的话:
Kernel32 INSTANCE = (Kernel32)
Native.loadLibrary("kernel32", Kernel32.class);

Kernel32 SYNC_INSTANCE = (Kernel32)
Native.synchronizedLibrary(INSTANCE); // 同步

[b]7. 最好将SYNC_INSTANCE 的作用域定义成局部的,方便JAVA垃圾回收.[/b]

[b]8. 结构映射[/b]
8.1 在接口内部编写一个静态类继承Structure

[b]9. 类型映射表[/b]
[url]http://jna.java.net/javadoc/overview-summary.html#marshalling[/url]

[b]10. JNAerator 自动本地库映射JAVA代码工具[/b]

JNAeratorStudio
[url]http://code.google.com/p/jnaerator/[/url]

[b]11. 传引用[/b]
// C声明
void allocate_buffer(char **bufp, int* lenp);

// JNA 映射
void allocate_buffer(PointerByReference bufp, IntByReference lenp);

// 用法
PointerByReference pref = new PointerByReference();
IntByReference iref = new IntByReference();
lib.allocate_buffer(pref, iref);
Pointer p = pref.getValue();
byte[] buffer = p.getByteArray(0, iref.getValue());

// 为什么这样就是传引用呢?
因为它传过去的不是对象本身,而是它的地址值.

[b]12. 数组映射[/b]
// C声明
void fill_buffer(int *buf, int len);
void fill_buffer(int buf[], int len); // same thing with array syntax

// 等价 JNA 映射
void fill_buffer(int[] buf, int len);

[b]13. Structures/Unions 映射[/b]
结构:
映射时需要与结构字段定义的顺序一致.

联合:
与结构类似,但必须设置使用setType表示激活的字段 .

Structures.ByReference
Structures.ByValue
标记型接口.表示结构体是引用或结构体本身.

[b]14. 官方例子[/b]
[url]http://java.net/projects/jna/sources/svn/show/trunk/jnalib/contrib[/url]

[b]15. 记录用户输入[/b]


package cn.bisoft.java.jna;

import com.sun.jna.Structure;
import com.sun.jna.platform.win32.BaseTSD;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.platform.win32.WinDef.HMODULE;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.platform.win32.WinUser.HHOOK;
import com.sun.jna.platform.win32.WinUser.HOOKPROC;
import com.sun.jna.platform.win32.WinUser.KBDLLHOOKSTRUCT;
import com.sun.jna.platform.win32.WinUser.LowLevelKeyboardProc;
import com.sun.jna.platform.win32.WinUser.MSG;

/**
* 低级键盘鼠标事件监听
* 此程序使用JNA实现类似键盘记录器程序或网页游戏傻瓜点击录制
*/
public class TrackUserInput {
private static volatile boolean quit;
private static HHOOK hhkKeyBoard;
private static HHOOK hhkMouse;
private static LowLevelKeyboardProc keyboardHook;
private static HOOKPROC mouseHook;

public static void main(String[] args) {
final User32 lib = User32.INSTANCE;
HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);

keyboardHook = new LowLevelKeyboardProc() {
public LRESULT callback(int nCode, WPARAM wParam,
KBDLLHOOKSTRUCT info) {
if (nCode >= 0) {
switch (wParam.intValue()) {
case WinUser.WM_KEYUP:
case WinUser.WM_KEYDOWN:
case WinUser.WM_SYSKEYUP:
case WinUser.WM_SYSKEYDOWN:
int keyCode = info.vkCode;

System.err.println(keyCode);
if (info.vkCode == 123) {
quit = true;
}
break;
}
}
return lib.CallNextHookEx(hhkKeyBoard, nCode, wParam,
info.getPointer());
}
};

mouseHook = new LowLevelMouseProc() {
public LRESULT callback(int nCode, WPARAM wParam,
MOUSEHOOKSTRUCT info) {
if (nCode >= 0) {
switch (wParam.intValue()) {
case MouseHook.WM_LBUTTONDOWN:
System.err.println("mouse left key down");
break;
case MouseHook.WM_LBUTTONUP:
System.err.println("mouse left key up");
break;
case MouseHook.WM_MBUTTONDOWN:
System.err.println("mouse middle key down");
break;
case MouseHook.WM_MBUTTONUP:
System.err.println("mouse middle key up");
break;
case MouseHook.WM_RBUTTONDOWN:
System.err.println("mouse right key down");
break;
case MouseHook.WM_RBUTTONUP:
System.err.println("mouse right key up");
break;
case MouseHook.WM_MOUSEMOVE:
// System.err.println("mouse mouse");
break;
}
}
return lib
.CallNextHookEx(hhkMouse, nCode, wParam, info.getPointer());
}

};

hhkKeyBoard = lib.SetWindowsHookEx(WinUser.WH_KEYBOARD_LL,
keyboardHook, hMod, 0);
hhkMouse = lib
.SetWindowsHookEx(WinUser.WH_MOUSE_LL, mouseHook, hMod, 0);

System.out.println("Enter '<F12>' to quit");

new Thread() {
public void run() {
while (!quit) {
try {
Thread.sleep(10);
} catch (Exception e) {
}
}

System.err.println("unhook and exit");
lib.UnhookWindowsHookEx(hhkKeyBoard);
lib.UnhookWindowsHookEx(hhkMouse);
System.exit(0);
}
}.start();

// 处理消息
int result;
MSG msg = new MSG();
while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) {
if (result == -1) {
System.err.println("error in get message");
break;
} else {
lib.TranslateMessage(msg);
lib.DispatchMessage(msg);
}
}

lib.UnhookWindowsHookEx(hhkKeyBoard);
lib.UnhookWindowsHookEx(hhkMouse);
}

public interface LowLevelMouseProc extends HOOKPROC {
LRESULT callback(int nCode, WPARAM wParam, MOUSEHOOKSTRUCT lParam);
}

public static class MOUSEHOOKSTRUCT extends Structure {
public static class ByReference extends MOUSEHOOKSTRUCT implements
Structure.ByReference {
};

public WinUser.POINT pt;
public WinDef hwnd;
public int wHitTestCode;
public BaseTSD.ULONG_PTR dwExtraInfo;
}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值