Java Native Interface(JNA)介绍
  • 2024-01-11 18:16:50
  • 3949 热度
  • 0 评论

JNA介绍

JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射。


https://github.com/java-native-access/jna 

http://java-native-access.github.io/jna/5.2.0/javadoc/ 


优点

JNA可以让你像调用一般java方法一样直接调用本地方法。就和直接执行本地方法差不多,而且调用本地方法还不用额外的其他处理或者配置什么的,也不需要多余的引用或者编码,使用很方便。


JNA描述

JNA类库使用一个很小的本地类库sub 动态的调用本地代码。程序员只需要使用一个特定的java接口描述一下将要调用的本地代码的方法的结构和一些基本属性。这样就省了为了适配多个平台而大量的配置和编译代码。因为调用的都是JNA提供的公用jar 包中的接口。


缺点

JNA是建立在JNI技术基础之上的一个Java类库,原来使用JNI,你必须手工用C写一个动态链接库,在C语言中映射Java的数据类型。JNA中,它提供了一个动态的C语言编写的转发器,可以自动实现Java和C的数据类型映射。你不再需要编写C动态链接库。当然,这也意味着,使用JNA技术比使用JNI技术调用动态链接库会有些微的性能损失。可能速度会降低几倍。但影响不大。


关于jna-platform

其实很多情况下,jna.jar就完全满足一般项目开发的需要了,比如数据 类型的映射和常用的方法等等,这些C/C++中基础的映射已经可以实现,包括一些基本的平台方法,但是,真实涉及到比较深入的平台方法的时候,就需要platform.jar的帮助了,platform.jar是依赖于jna.jar实现的,包括了FileMonitor、FileUtils、KeyboardUtils、WindowUtil等Win32和平台相关的简化动态访问功能类中的大部分常用方法,为开发者开发自己的跨平台映射方法提供参考。

所以,platform.jar对于jna.jar是一种补充和扩展,jna.jar相当于核,platfrorm.jar相当于增量插件。


Maven引用:

<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.5.1</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>4.5.1</version>
</dependency>


使用的函数必须与链接库中的函数原型保持一致,这是JNA甚至所有跨平台调用的难点,因为C/C++的类型与Java的类型是不一样的,你必须转换成java对应类型让它们保持一致,这就是类型映射(Type Mappings),JNA官方给出的默认类型映射表如下:

20190430151334464.png

其中类型映射的难点在于结构体、指针和函数回调。


示例代码,打开一个Win窗口:

package com.mt.test.jna;
import com.sun.jna.Callback;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Kernel32Util;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.User32Util;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinUser;
public class CWindow {
	public static void main(String[] args) {
		CWindow win = new CWindow();
		win.test();
	}
    class WindowProc implements Callback {
        public WinDef.LRESULT callback(WinDef.HWND hwnd, WinDef.UINT uMsg, WinDef.WPARAM wParam, WinDef.LPARAM lParam) {
            switch (uMsg.intValue()) {
                case WinUser.WM_CLOSE:
                    User32.INSTANCE.PostQuitMessage(0);
                    break;
            }
            return User32.INSTANCE.DefWindowProc(hwnd, uMsg.intValue(), wParam, lParam);
        }
    }
    public boolean test() {
        String wndClassName = "窗口注册名称";
        String wndTitle = "这是窗口标题";
        WinDef.HINSTANCE hInstance = null;
        WinUser.WNDCLASSEX wndClassEx = new WinUser.WNDCLASSEX();
        wndClassEx.lpfnWndProc = new WindowProc();
        wndClassEx.cbClsExtra = 0;
        wndClassEx.cbWndExtra = 0;
        wndClassEx.style = 1|2;
        wndClassEx.lpszClassName = wndClassName;
        wndClassEx.hInstance = hInstance;
        wndClassEx.hCursor = null;
        wndClassEx.hIcon = null;
        wndClassEx.hbrBackground = null;
        wndClassEx.lpszMenuName = null;
        if(User32.INSTANCE.RegisterClassEx(wndClassEx).intValue()==0) {
            System.out.println("register window failed!");
            System.out.println(""+ Kernel32.INSTANCE.GetLastError() + "\n"+Kernel32Util.getLastErrorMessage());
            return false;
        }
        WinDef.HWND hWnd = User32Util.createWindowEx(0, wndClassName, wndTitle, WinUser.WS_OVERLAPPEDWINDOW,
                100, 100, 500, 400, null, null, hInstance, null);
        if(hWnd==null) {
            System.out.println("create window failed!");
            System.out.println(""+ Kernel32.INSTANCE.GetLastError() + "\n"+Kernel32Util.getLastErrorMessage());
            return false;
        }
        User32.INSTANCE.ShowWindow(hWnd, WinUser.SW_SHOWNORMAL);
        User32.INSTANCE.UpdateWindow(hWnd);
        WinUser.MSG msg = new WinUser.MSG();
        while (User32.INSTANCE.GetMessage(msg, hWnd, 0, 0)!=0) {
            User32.INSTANCE.TranslateMessage(msg);
            User32.INSTANCE.DispatchMessage(msg);
        }
        return true;
    }
}


END


alay

Flame

Hello world!

0 评论
留下评论