在 Java 中使用 JNI 调用 DLL(Dynamic Link Library)可以实现与底层 C/C++代码的交互。下面我将介绍两种常见的方式来实现这种调用:一种是基于手动加载的方式,另一种是使用 JNA 库来简化 JNI 调用。
C/C++代码(example.c):
#include <stdio.h>
JNIEXPORT void JNICALL Java_com_example_MyClass_printHello(JNIEnv *env, jobject obj) {
printf("Hello from DLL!\n");
}
Java 代码(MyClass.java):
package com.example;
public class MyClass {
static {
System.loadLibrary("example"); // 加载名为example的DLL
}
public native void printHello(); // 声明本地方法
public static void main(String[] args) {
MyClass myClass = new MyClass();
myClass.printHello(); // 调用本地方法
}
}
编译和运行:
# 编译C代码生成DLL
gcc -shared -o example.dll -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" example.c
# 编译Java代码
javac com/example/MyClass.java
# 运行Java程序
java com.example.MyClass
JNA(Java Native Access)库简化了 JNI 调用,它允许直接在 Java 中调用本地库中的函数,无需手动加载。
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.9.0</version>
</dependency>
implementation 'net.java.dev.jna:jna:5.9.0'
C/C++代码(example.c) 同上。
Java 代码(MyLibrary.java):
package com.example;
import com.sun.jna.Library;
import com.sun.jna.Native;
public interface MyLibrary extends Library {
MyLibrary INSTANCE = Native.load("example", MyLibrary.class);
void printHello();
}
public class Main {
public static void main(String[] args) {
MyLibrary.INSTANCE.printHello(); // 调用本地方法
}
}
在这个例子中,MyLibrary
接口声明了需要从本地库中调用的函数,并使用 JNA 的 Native.load
方法加载了本地库。
运行:
# 编译C代码生成DLL(同上)
# 编译Java代码
javac com/example/MyLibrary.java
# 运行Java程序
java com.example.Main
无论选择哪种方式,都需要注意将编译后的 DLL 文件放在 Java 程序能够找到的位置,以便正确加载。