zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    移植Valgrind检测Android JNI内存泄漏
    【转】线性回归最小二乘法和梯度下降法
    【转】成为一名推荐系统工程师永远都不晚
    vue-element-admin使用常见问题
    SpringBoot中如何使用jpa和jpa的相关知识总结
    SpringBoot Controller接收参数的几种常用方式
    java项目其他基础配置
    eclipse 新建 maven 项目 + 消除错误
    vue城市三级联动组件 vue-area-linkage
    Vue中watch的简单应用
  • 原文地址:https://www.cnblogs.com/ZiYangZhou/p/12182097.html
Copyright © 2011-2022 走看看