什么是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