当前位置: 首页 > 知识库问答 >
问题:

JNA结构。getFieldOrder()与声明的字段名不匹配

田修为
2023-03-14

我在结构中定义JNA结构时遇到以下异常:

线程“main”Java . lang中出现异常,错误:类com上的Structure.getFieldOrder()。MyInterface$mine$ByReference返回与声明的字段名称不匹配的名称([color,data,hello,rice,str,wild])

查看我的Cpp结构:

typedef struct s_mine
{
    e_color           color;    //e_color is enum type made of int values
    his               data;        
    int               str;        
    unsigned int      wild;         
    unsigned int      hello;        
    float             rice; 
} mine;

typedef struct s_his
{
    unsigned char * data; 
    unsigned int    size; 
} his;

请参阅下面的示例,即MyInterface.java:

public interface MyInterface extends Library {

    public static class his extends Structure {
        public static class ByReference extends his implements Structure.ByReference {} // Need the stucture address as it a parameter of a particular wrapped method
        public static class ByValue extends his implements Structure.ByValue {}         // Need the structure value inside "mine" Structure
        public Pointer data;
        public int size;
        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList(new String[] { "data", "size"});
        }
    }
    
    public class mine extends Structure {
        public static class ByReference extends mine implements Structure.ByReference {}
        int color; 
        his.ByValue data;
        int str; 
        int wild; 
        int hello; 
        float rice;

        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList(new String[] {"color","data","str","wild","hello","rice"});
        }
    }
}

使用 MyInterface 的主类包含以下行,我对“我的”结构字段的顺序有例外:

final MyInterface.mine.ByReference mine_ref = new MyInterface.mine.ByReference();   

因此,我调试代码,以便进入JNA遵循结构。类转换为下面的getFields方法(在该方法中,我得到了异常(下面的第二个):

    protected List<Field> getFields(boolean force) {
        List<Field> flist = getFieldList();
        Set<String> names = new HashSet<String>();
        for (Field f : flist) {
            names.add(f.getName());
        }

        List<String> fieldOrder = fieldOrder();
        if (fieldOrder.size() != flist.size() && flist.size() > 1) {
            if (force) {
                throw new Error("Structure.getFieldOrder() on " + getClass()
                                + (fieldOrder.size() < flist.size()
                                    ? " does not provide enough"
                                    : " provides too many")
                                + " names [" + fieldOrder.size()
                                + "] ("
                                + sort(fieldOrder)
                                + ") to match declared fields [" + flist.size()
                                + "] ("
                                + sort(names)
                                + ")");
            }
            return null;
        }

        Set<String> orderedNames = new HashSet<String>(fieldOrder);
        if (!orderedNames.equals(names)) {
            throw new Error("Structure.getFieldOrder() on " + getClass()
                            + " returns names ("
                            + sort(fieldOrder)
                            + ") which do not match declared field names ("
                            + sort(names) + ")");
        }

        sortFields(flist, fieldOrder);
        return flist;
    }

这是当getFields方法中出现异常时,我在研究以下字段值时得到的结果

fieldOrder = [color, data, str, wild, hello, rice]
orderedNames = [str, color, data, hello, rice, wild]

引发异常是因为名称为空。无论如何,由于HashSetjava.util类不能保证顺序会随着时间的推移保持不变,我肯定认为JNA中存在错误Structure.java.因为我的field dOrder的顺序是由new HashSet以随机顺序排序的。

>

  • 有没有人同意我的观点,或者我是否错过了关于声明和使用我的JNA结构的方式?

    如果没有错误(即故意使用HashSet...),我是否在声明我的结构时犯了什么错误?如何解决此问题?


  • 共有1个答案

    戚兴思
    2023-03-14
    匿名用户

    您的错误出现在我的结构中:您需要将字段声明为public。JNA使用反射,并依赖于public修饰符来处理要映射到本机的字段;否则,它们只是类中的helper字段。

    否则,映射将按原样工作,但请考虑以下改进:

      < li >当用作嵌套结构时,不需要使用结构的< code>ByValue版本。这是默认的。只有当嵌套结构是< code>ByReference时,才需要对其采取特殊操作。 < ul > < li >同样,< code>ByReference在用作函数参数时是默认值。只有当函数需要< code>ByValue参数时,才需要特殊处理。
    @FieldOrder({"data", "size"})
    class his extends Structure { 
      // etc... 
    }
    
    • 接口变量/类/等默认为public静态最终,因此使用这些修饰符是多余的。

     类似资料:
    • 本文向大家介绍C++中声明类的class与声明结构体的struct关键字详解,包括了C++中声明类的class与声明结构体的struct关键字详解的使用技巧和注意事项,需要的朋友参考一下 class class 关键字声明类类型或定义类类型的对象。 语法 参数 template-spec 可选模板说明。 ms-decl-spec 可选存储类说明有关更多信息 tag 给定于类的类型名称。在类范围内的

    • 我已经建立了一个字段声明列表,需要找出每个字段的名称: 我找不到任何检索字段名称的方法。 奇怪的是,其中一个构造函数确实接受一个字段参数,所以不确定为什么它没有getter。我需要从另一个节点获取它吗? FieldDeclaration(节点列表修饰符、类型、字符串名称)创建一个FieldDeclaration。https://www.javadoc.io/doc/com.github.javap

    • 问题内容: 编译错误: 解决办法? 问题答案: Java不允许您在函数局部内部类内定义非最终静态字段。只允许顶级类和静态嵌套类具有非最终静态字段。 如果您要在班级中添加一个字段,请将其放在班级级别,如下所示:

    • 问题内容: 从golang规范 是否有使用内的 空白 字段的实际方案?(一些代码片段将不胜感激) 问题答案: 填充正是所谓的:一些填充,用于将以下字段与您的需求对齐,例如,匹配C结构的布局。无法访问它(至少在没有软件包不安全的情况下)。

    • 问题内容: package main 结构中无名字段的目的是什么? 是否可以像使用命名字段一样访问这些字段? 问题答案: 请参阅“ 在Go中嵌入 ”:您在结构中嵌入了一个匿名字段:通常与嵌入式结构一起使用,而不是像这样的基本类型。该类型没有要显示的“提升字段”。 字段或方法在一个结构匿名字段的被称为 促进 如果是一个合法的选择器,它表示字段或方法。 提升的字段的作用类似于结构的普通字段,只是它们不

    • 问题内容: 在没有泛型类型的类中,我想声明一个类似于以下内容的相当复杂的泛型字段: 问题是Java编译器不会让我:) 所以我的问题是如何正确地引入T和S,而又不向类Client添加类型。 我的目标是强制成为您选择的类的子类型和作为子类。 问题答案: 你不能 唯一的选择是在类声明中声明泛型类型参数。如果您的类没有泛型类型参数,则其成员不能为泛型。您必须在类成员的声明中使用实际类型。