jna structure.getfieldorder()与声明的字段名不匹配

oprakyz7  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(1949)

我在结构中定义jna结构时遇到以下异常:
线程“main”java.lang.error中出现异常:类com.myinterface$mine$byreference上的structure.getfieldorder()返回与声明的字段名不匹配的名称([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的主类包含以下行,在该行上我有一个关于“mine”结构字段顺序的异常:

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

因此,我调试代码,以便将jna以下structure.class步进以下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]

由于名称为空,引发了异常。无论如何,由于hashset java.util类不能保证随着时间的推移顺序保持不变,我肯定认为jna structure.java中存在bug。因为我的fieldorder的顺序是按照 new HashSet<String>(fieldOrder) 指令,因此不同于orderednames的顺序。
有没有人同意我的观点,或者我遗漏了一些关于如何声明和使用我的jna结构的内容?
如果没有bug(即hashset是故意使用的……),那么我是否在声明我的结构时出错了?我如何解决这个问题?

emeijp43

emeijp431#

你的错误在 mine 结构:需要将字段声明为 public . jna使用反射并依赖于 public 要Map到本机的字段的修饰符;否则,它们只是类中的助手字段。
否则,Map将按您的方式工作,但请考虑以下改进:
你不需要使用 ByValue 用作嵌套结构时的结构版本。这是默认值。唯一需要对嵌套结构执行特殊操作的时间是 ByReference .
同样地, ByReference 是用作函数参数时的默认值。仅当函数需要 ByValue 它是否需要特殊处理。
使用 getFieldOrder() 在jna 5.x中,重写被替换为 @FieldOrder 注解。当你所拥有的东西起作用的时候,如果你只是把注解放在你的结构之前,你的代码更可读,例如。,

@FieldOrder({"data", "size"})
class his extends Structure { 
  // etc... 
}

默认情况下,接口变量/类/等 public , static ,和 final 所以使用这些修饰语是多余的。

相关问题