JNA (Java Native Access) 建構於 JNI 之上,由 Sun 主導開發的開源框架。讓 Java 直接呼叫原生庫 (Windows .dll / Linux .so) 無需撰寫 C/C++ 胶水代碼,自動處理資料型別對應。雖效能略遜於 JNI,但開發效率大幅提升。
#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport) __stdcall
#else
#define DLL_EXPORT __declspec(dllimport) __stdcall
#endif
#ifdef __cplusplus
extern "C" {
#endif
int DLL_EXPORT add(int a, int b);
#ifdef __cplusplus
}
#endif
#endif
#include "main.h"
int DLL_EXPORT add(int a, int b) {
return a + b;
}
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
return TRUE;
}
關鍵點:使用 __stdcall 呼叫慣例,配合 extern "C" 避免 C++ 名稱修飾。
import com.sun.jna.Native;
import com.sun.jna.win32.StdCallLibrary;
public class JnaDemo {
// 繼承 StdCallLibrary 對應 __stdcall
public interface CLibrary extends StdCallLibrary {
CLibrary INSTANCE = (CLibrary) Native.loadLibrary("forjava", CLibrary.class);
int add(int a, int b);
}
public static void main(String[] args) {
System.out.println("2 + 3 = " + CLibrary.INSTANCE.add(2, 3)); // 輸出 5
}
}
| C/C++ 型別 | JNA 型別 | Java 型別 |
|---|---|---|
| int | int | int |
| long | long | long |
| float | float | float |
| double | double | double |
| char* | String | String |
| void* | Pointer | Pointer |
| struct* | Structure | extends Structure |
interface Callback extends StdCallLibrary {
interface MyCallback extends StdCallCallback {
void callback(int value);
}
void registerCallback(MyCallback cb);
}
class Point extends Structure {
public int x, y;
protected List<String> getFieldOrder() { return Arrays.asList("x", "y"); }
}
Pointer 需手動 free()Memory 物件減少 GC 壓力java.library.path,或 32/64 位元不匹配StdCallLibrary,C 預設 Library (cdecl)WString / Native.toString(bytes, encoding)