什麼是JNA
- JNA全稱Java Native Access,是JNI之外另一個Java訪問C++的混編框架
- JNA非Java自帶功能,需要導入第三方類庫
- JNA只支持Java調用C++,不支持C++調用Java
- JNA對C++代碼和編譯無特殊要求,普通的C++代碼都可調用,非常方便
- JNA直接將dll文件加載爲一個接口對象,只要定義一個接口,裏面包含和C++同名的方法即可,使用非常方便
- JNA在Java和C++兩端編碼都十分方便,這正是它流行的原因
- JNA的效率遠低於JNI,可達百倍之多,方便的同時帶來的必然是性能損失。但是偶爾調用影響並不大,所以它在大多時候仍是首選。在Java和C++互調非常頻繁的場景下,應當使用JNI
JNA調用DLL示例
JNA開發包下載地址:Java Native Access 5.5.0
//hello.cpp
#include <iostream>
extern "C" __declspec(dllexport)
void hello() {
std::cout << "Hello World" << std::endl;
}
extern "C" __declspec(dllexport)
int sum(int a, int b) {
return a + b;
}
extern "C" __declspec(dllexport)
void printMessage(wchar_t *message) {
std::wcout << message << std::endl;
}
//CMakeLists.txt
project(hello)
set(CMAKE_CXX_STANDARD 17)
add_library(
hello SHARED
hello.cpp
)
//JnaHello.java
package com.easing.java;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.WString;
public interface JnaHello extends Library {
JnaHello INSTANCE = Native.loadLibrary("libhello", JnaHello.class);
void hello();
void printMessage(WString message);
int sum(int a, int b);
}
//Hello.java
package com.easing.java;
import com.sun.jna.WString;
public class Hello {
public static void main(String[] args) {
JnaHello.INSTANCE.hello();
JnaHello.INSTANCE.printMessage(new WString("JNA Demo"));
int sum = JnaHello.INSTANCE.sum(100, 300);
System.out.println("sum result is " + sum);
}
}
JNA Class類型
只要定義一個Java類,實現Structure接口,即可對應C++中的class/struct類型
JNA類型對照表
Java Type | Native Type |
---|---|
int | int |
Native Long | long |
double | double |
boolean | int |
byte | char |
char | wchar_t |
String | char* |
WString | wchar_t* |
array | pointer array |
Buffer/Pointer | void* |
String[] | char** |
WString[] | wchar_t** |
Structure | struct |
Callback | (*pFunc)() |
JNA使用注意事項
- 中文字符要使用WString,在C++中要通過printf或wcout打印,cout無法打印中文
- 在IntelliJ Idea中,JNA會從Source和Resource目錄中查找dll(可右鍵文件夾,通過Make Directory as菜單設置目錄種類,見下圖),注意dll放置的位置
- 打包成Jar包後,JNA會從運行目錄和操作系統的path環境變量中查找dll,將dll放在Jar包同目錄下,或者任意一個path目錄下,均可以
- 如果C++使用到了iostream等C++標準庫,則需要依賴C++ std相關的dll,如果你的電腦上所有path目錄下均不存在這些dll,則會報錯,可以手動下載std支持庫來解決,放到工程dll相同位置即可
- C++標準庫相關dll下載:JNA C++ Std Support Library