java系统中调用dll动态链接库需要用到JNA作为桥接工具,特此记录一下JNA的使用方式。
引入JNA的jar包
直接下载或者通过maven导入jar包,maven引入版本为5.5.0的JNA配置如下
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna-platform -->
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.5.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.5.0</version>
</dependency>
Hello World
通过JNA调用C标准库的printf()函数。
package test.javatest.jna;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
public class HelloWorld {
public interface CLibrary2 extends Library {
CLibrary2 INSTANCE = (CLibrary2) Native.load((Platform.isWindows() ? "msvcrt" : "c"), CLibrary2.class);
void printf(String format, Object... args);
}
public static void main(String[] args) {
CLibrary2.INSTANCE.printf("Hello, World\n");
for (int i = 0; i < args.length; i++) {
CLibrary2.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
}
}
}
类型映射
官方文档 Default Type Mappings# Default Type Mappings
Native Type | Size | Java Type | Common Windows Types |
---|---|---|---|
char | 8-bit integer | byte | BYTE, TCHAR |
short | 16-bit integer | short | WORD |
wchar_t | 16/32-bit character | char | TCHAR |
int | 32-bit integer | int | DWORD |
int | boolean value | boolean | BOOL |
long | 32/64-bit integer | NativeLong | LONG |
long long | 64-bit integer | long | __int64 |
float | 32-bit FP | float | - |
double | 64-bit FP | double | - |
char* | C string | String | LPCSTR |
void* | pointer | Pointer | LPVOID, HANDLE, LP_XXX_ |
返回值和参数
获取函数返回值
有加密文件接口int encryptFile(char* filePath,char* key),其中filePath为输入的文件路径,key为输入的秘钥,返回值0或者1标识是否加密成功。
根据类型映射定义接口
int encryptFile(String filepath, String key);
调用接口
@Test
public void testEncryptFile() {
try {
int code = ThirdpartyLib.INSTANCE.encryptFile("D:\\test\\测试文档.pdf", "123456");
System.out.println("testEncryptFile code = " + code);
} catch (Exception e) {
e.printStackTrace();
}
}
获取函数的参数返回值
有获取秘钥接口void getEncryptKey(char* encryptKey,int* size),其中encryptKey为输出的秘钥,size为输入的秘钥长度。
使用Pointer类型定义接口
void getEncryptKey(Pointer encryptKeyPointer,IntByReference intByReference);
调用接口,指针类型类型输出参数的接口我们需要预先开辟一块指定大小的内存区域用于存放数据,需要提前知道或者预估出数据的大小。对于指针类型的输出参数根据具体情况使用IntByReference
,LongByReference
,PointerByReference
,Pointer
等。
@Test
public void testGetEncryptKey() {
Pointer pointer = new Memory(128);
IntByReference intByReference = new IntByReference();
ThirdpartyLib.INSTANCE.getEncryptKey(pointer,intByReference);
System.out.println("testGetEncryptKey encryptKey = " + pointer.getString(0) + " ,size = " + intByReference.getValue());
pointer.getPointer(0);
}
完整代码
package test.javatest.jna;
import org.junit.Test;
import com.sun.jna.Library;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
public class JNATest {
public interface ThirdpartyLib extends Library {
ThirdpartyLib INSTANCE = Native.load("D:\\test\\DLL\\test\\bin\\Debug\\test.dll", ThirdpartyLib.class);
int encryptFile(String filepath, String key);
void getEncryptKey(Pointer encryptKeyPointer,IntByReference intByReference);
}
@Test
public void testEncryptFile() {
try {
int code = ThirdpartyLib.INSTANCE.encryptFile("D:\\test\\测试文档.pdf", "123456");
System.out.println("testEncryptFile code = " + code);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testGetEncryptKey() {
Pointer pointer = new Memory(128);
IntByReference intByReference = new IntByReference();
ThirdpartyLib.INSTANCE.getEncryptKey(pointer,intByReference);
System.out.println("testGetEncryptKey encryptKey = " + pointer.getString(0) + " ,size = " + intByReference.getValue());
pointer.getPointer(0);
}
}
参考
https://github.com/java-native-access/jna
https://blog.csdn.net/blog_abel/article/details/32334881
原文地址:https://www.cnblogs.com/ZiYangZhou/p/12182097.html
时间: 2024-10-10 13:16:36