3Dayss 2024-07-20 15:12 采纳率: 33.3%
浏览 3

关于#java#的问题:protected List

有关于Java调用ControlCAN.dll程序发生的问题。
在尝试调用一个CAN通讯的dll程序,有一个接口方法需要放数组,但是这个数组的创建出了问题,会报错“java.lang.IllegalStateException: Array fields must be initialized”,想求助如何解决。

主调试程序:

import com.sun.jna.Library;
import com.sun.jna.Native;

public class CanUtil {
    public interface testDlls extends Library {
        Integer VCI_OpenDevice(Integer DevType, Integer DevIndex, Integer Reserved);
        Integer VCI_CloseDevice(Integer DevType, Integer DevIndex);
        Integer VCI_Transmit(Integer DeviceType, Integer DeviceInd, Integer CANInd, VCI_CAN_OBJ[] pSend, Integer Length);
    }
    
    public static void main(String[] args) {
        try {
            testDlls dll = (testDlls) Native.loadLibrary("ControlCAN", testDlls.class);  // ControlCAN.dll
            System.out.println("2222");
            
            // 数组容量
            int cycle = 2;
            
            // 结构体映射的实体类
            VCI_CAN_OBJ unit = new VCI_CAN_OBJ();
            
            // 通过实体类继承的Structure类中的toArray(arraySize)方法获得连续存储地址的数组
            VCI_CAN_OBJ[] vco = (VCI_CAN_OBJ[]) unit.toArray(cycle);// <<---- 就是在这里发生报错: java.lang.IllegalStateException: Array fields must be initialized
//            VCI_CAN_OBJ[] vco = new VCI_CAN_OBJ[cycle];
            for (int i = 0; i < cycle; i++) {
                vco[i] = new VCI_CAN_OBJ();
                vco[i].ID = (byte)i;
                vco[i].RemoteFlag = (byte)0;
                vco[i].ExternFlag = (byte)0;
                vco[i].DataLen = (byte)1;
                byte[] data = new byte[1];
                data[0] = 0x66;
                vco[i].Data = data;
            }
            
            for(VCI_CAN_OBJ obj : vco) {
                obj.toString();
            }
            
            Integer result = -2;
            result = dll.VCI_Transmit(4, 0, 0, vco, cycle);
            System.out.println("result: " + result);

        } catch (Exception e) {
            // TODO: handle exception
            System.out.println(e.toString());
            e.printStackTrace();
        }
    }
}

VCI_CAN_OBJ实体类:

import com.sun.jna.Structure;;

public class VCI_CAN_OBJ extends Structure {
    public byte ID;
    
    public byte RemoteFlag;
    
    public byte ExternFlag;
    
    public byte DataLen;
    
    public byte[] Data;
    
    //定义取值次序,需要与C/C++中对齐,不然会出现NoSuchFieldError
    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList(new String[]{"ID", "RemoteFlag", "ExternFlag", "DataLen", "Data"});
    }
    
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("ID: " + this.ID + ", ");
        sb.append("RemoteFlag: " + this.RemoteFlag + ", ");
        sb.append("ExternFlag: " + this.ExternFlag + ", ");
        sb.append("DataLen: " + this.DataLen + ", ");
        if (Data != null) {
            sb.append(" { ");
            for(byte unit : Data) {
                sb.append(unit + ", ");
            }
            sb.replace(sb.length()-2, sb.length(), " } ");
        }
        return sb.toString();
    }

}

  • 写回答

3条回答 默认 最新

  • 阿里嘎多学长 2024-07-20 15:12
    关注

    以下内容由AIGC及阿里嘎多学长共同生成、有用望采纳:


    根据您提供的信息和代码,问题出在尝试使用Structure类的方法toArray来创建数组时。toArray方法通常用于将Structure对象的字段转换为一个连续的字节数组,而不是创建一个对象数组。这就是为什么您在尝试使用toArray方法时遇到了java.lang.IllegalStateException: Array fields must be initialized异常。

    要解决这个问题,您应该直接声明并初始化VCI_CAN_OBJ类型的数组,然后填充它,而不是使用toArray方法。以下是修改后的代码示例:

    // ... 其他代码 ...
    
    public static void main(String[] args) {
        try {
            testDlls dll = (testDlls) Native.loadLibrary("ControlCAN", testDlls.class);
            System.out.println("2222");
    
            // 数组容量
            int cycle = 2;
    
            // 初始化数组
            VCI_CAN_OBJ[] vco = new VCI_CAN_OBJ[cycle];
            for (int i = 0; i < cycle; i++) {
                vco[i] = new VCI_CAN_OBJ();
                vco[i].ID = (byte)i;
                vco[i].RemoteFlag = (byte)0;
                vco[i].ExternFlag = (byte)0;
                vco[i].DataLen = (byte)1;
                byte[] data = new byte[1];
                data[0] = 0x66;
                vco[i].Data = data;
            }
    
            // ... 其他代码 ...
    
        } catch (Exception e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
    }
    

    请注意,我已经移除了unit.toArray(cycle)这一行,因为它是不正确的用法。现在,我们直接声明了一个VCI_CAN_OBJ类型的数组,并使用循环来初始化它。

    另外,确保VCI_CAN_OBJ类中的getFieldOrder方法返回的字段顺序与C/C++中的结构体定义一致,这是非常重要的,因为JNA(Java Native Access)库使用这个顺序来正确地映射Java对象到C结构体。

    最后,编译并运行您的程序,检查是否还存在问题。如果一切顺利,您应该不会再遇到初始化数组时的错误。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 7月20日

悬赏问题

  • ¥15 onlyoffice编辑完后立即下载,下载的不是最新编辑的文档
  • ¥15 求caverdock使用教程
  • ¥15 Coze智能助手搭建过程中的问题请教
  • ¥15 12864只亮屏 不显示汉字
  • ¥20 三极管1000倍放大电路
  • ¥15 vscode报错如何解决
  • ¥15 前端vue CryptoJS Aes CBC加密后端java解密
  • ¥15 python随机森林对两个excel表格读取,shap报错
  • ¥15 基于STM32心率血氧监测(OLED显示)相关代码运行成功后烧录成功OLED显示屏不显示的原因是什么
  • ¥100 X轴为分离变量(因子变量),如何控制X轴每个分类变量的长度。