JNA调用DLL简单使用

Posted ziyangzhou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JNA调用DLL简单使用相关的知识,希望对你有一定的参考价值。

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
");
        for (int i = 0; i < args.length; i++) {
            CLibrary2.INSTANCE.printf("Argument %d: %s
", 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

以上是关于JNA调用DLL简单使用的主要内容,如果未能解决你的问题,请参考以下文章

Java跨语言调用,使用JNA访问Java外部接口

java使用JNA框架调用dll动态库

jna调用c编写的dll

java使用jna加载dll文件可以运行成功,打包后运行jar文件却找不到dll文件

java用jna调用C语言dll接口中的回调函数怎么写

使用 JNA 从 Java 调用 C++ dll 方法并避免方法名称修改