zoukankan      html  css  js  c++  java
  • JNA使用总结

    这两天工作有一项任务,需要用 java 去调用 c 语言编写的 SDK,用到了 JNA,用的过程中遇到了些问题,在这里总结下使用方法,记录下。

    分为几个步骤:编写一个继承了 Library 的接口,在类中声明接口,编写结构体(如果有需要),调用接口。

    1. 编写 Library 接口

      在接口中声明的方法要和 SDK 的函数对应上,方法名要对应函数名。

      参数的话,基本类型一样,指针对应 Pointer、XxxByReference,结构体的对应需要自定义 java 类。详情可以参见 https://yq.aliyun.com/articles/606236?utm_content=m_1000018939 中的表格。

      调用接口时,使用 Native.loadLibrary("dll文件路径") 来生成一个代理对象,然后调用代理对象中的方法。

      示例代码如下:

    public interface ChengFengSDK extends Library {
    
        /**
         * 生成一个代理对象,后面使用时,需要调用 INTERFACE 中的接口,然后代理对象来调用 C 语言的实现。
         */
        ChengFengSDK INTERFACE = (ChengFengSDK) Native.loadLibrary("HieClientUnit", ChengFengSDK.class);
    
        /**
         * 接口声明,方法名和参数列表要与头文件的函数对应起来
         */
        int HieClient_UserLogin  (WinNT.HANDLEByReference hUser, UserLoginPara.ByReference cUserLoginPara);
        int HieClient_Start();
        int HieClient_Stop();
    
    }

    2. 自定义结构体

      当函数的参数中存在结构体时,java 里需要自定义一个类来与之对应。

      编写一个类,继承 Structure。

      类中的属性与结构体中的属性要一一对应,并且全都要是 public 权限。

      重写 getFieldOrder 方法,List 中的名称顺序要与函数的参数列表一致。

      注意,如果函数中的参数为指针类型,则传入的结构体类需要继承 Structure.ByReference,否则会抛内存访问错误。

      示例代码如下:

    public class UserLoginPara extends Structure {
    
        public byte[] sServerIP = new byte[256];
        public int dwCommandPort;
        public byte[] sUName = new byte[32];
        public byte[] sUPass = new byte[32];
        public int[] dwReserve = {0, 1};
    
        // 如果是指针类型,用这个
        public static class ByReference extends UserLoginPara implements Structure.ByReference { }
        public static class ByValue extends UserLoginPara implements Structure.ByValue { }
    
        protected List getFieldOrder() {
            return Arrays.asList(new String[]{"sServerIP", "dwCommandPort", "sUName", "sUPass", "dwReserve"});
        }
    }

    3. 调用接口

      要注意,数组需要初始化,大小要与 C 语言中的大小一致。

      示例代码如下:

        WinNT.HANDLE hUserLogin = WinBase.INVALID_HANDLE_VALUE;
        WinNT.HANDLEByReference hUserLoginRef = new WinNT.HANDLEByReference(hUserLogin);
    
        //配置用户登录参数
        UserLoginPara.ByReference tLoginPara = new UserLoginPara.ByReference();
        tLoginPara.dwCommandPort = port;    //端口
        System.arraycopy(ip.getBytes(), 0, tLoginPara.sServerIP, 0, ip.getBytes().length);  //ip
        System.arraycopy(userName.getBytes(), 0, tLoginPara.sUName, 0, userName.getBytes().length); //用户名
        System.arraycopy(passwd.getBytes(), 0, tLoginPara.sUPass, 0, passwd.getBytes().length);
    
        //调用登录接口
        nLoginCode = sdk.HieClient_UserLogin(hUserLoginRef, tLoginPara);
  • 相关阅读:
    在 Docker 搭建 Maven 私有库
    Maven:mirror和repository 区别
    ubuntu DEBIAN_FRONTEND环境变量用法
    Redis常见面试题
    Error:(1, 1) java: 非法字符: ‘ufeff’
    jpa 查询方法和sql查询语句对应关系
    net.sf.json.JSONObject对时间戳的格式化处理
    美团Leaf——全局序列生成器
    Logstash
    Kafka和SpringBoot
  • 原文地址:https://www.cnblogs.com/lighter-blog/p/11060862.html
Copyright © 2011-2022 走看看