Linux 下 JNA 調用動態連接庫文件 so
- JNA
- 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
https://java-native-access.github.io/jna/5.3.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
相當於增量插件。
- JNA 使用
- pom.xml 引入
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.13.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.13.0</version>
</dependency>
使用的函數必須與鏈接庫中的函數原型保持一致,這是 JNA 甚至所有跨平臺調用的難點,因爲 C/C++ 的類型與 Java 的類型是不一樣的,必須轉換成 java 對應類型讓它們保持一致,這就是類型映射(Type Mappings),JNA 官方給出的默認類型映射表如下:
其中類型映射的難點在於結構體、指針和函數回調。
- 創建頭文件 TestJna.h
#ifndef _TestJna_h
#define _TestJna_h
#ifdef __cplusplus
extern "C" {
#endif
int add(int a, int b);
int sub(int a, int b);
#ifdef __cplusplus
}
#endif
#endif
- 創建頭文件 TestJna.cpp
#include "TestJna.h"
extern "C" int add(int a, int b){
return a+b;
}
extern "C" int sub(int a, int b){
return a-b;
}
**注意:**一定要加extern "C"
否則生成的方法名跟 cpp 文件定義的方法名不一致。
查看 so 方法名
nm -D libTestJnaEx.so | grep add
nm -D libTestJnaEx.so | grep sub
- 生成動態連接庫 so 文件
g++ TestJna.cpp -fPIC -shared -o libTestJnaEx.so
- 拷貝 so 文件到 / usr/lib 目錄
cp libTestJnaEx.so /usr/lib
- 創建 TestJna.java 文件
import com.sun.jna.Library;
import com.sun.jna.Native;
public class TestJnaEx {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary) Native.load("TestJnaEx", CLibrary.class);
int add(int a, int b);
int sub(int a, int b);
}
public static void main(String[] args) {
int sum = CLibrary.INSTANCE.add(2, 3);
System.out.println(sum);
int diff = CLibrary.INSTANCE.sub(5, 3);
System.out.println(diff);
}
}
導出可執行 jar 文件TestJnaEx.jar
- 執行 TestJnaEx.jar
java -jar TestJnaEx.jar
結果
師傅領進門,修行在個人。
參考
https://blog.csdn.net/y666666y/article/details/128303464
https://www.javacui.com/java/520.html
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/jo6ALehyy6FOak1LGb44zA