首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >JNA Structure.getFieldOrder()与声明的字段名不匹配

JNA Structure.getFieldOrder()与声明的字段名不匹配
EN

Stack Overflow用户
提问于 2020-11-14 15:59:09
回答 1查看 1.6K关注 0票数 1

在结构中定义JNA结构的例外情况如下:

线程"main“中的

异常java.lang.Error: Structure.getFieldOrder()在com.MyInterface$mine$ByReference类上返回名称(颜色、数据、hello、rice、str、野生),这些名称与声明的字段名不匹配

请参阅我的Cpp结构:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
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的主类包含以下行,其中我对“‘s”结构字段的顺序有异常:

代码语言:javascript
运行
复制
final MyInterface.mine.ByReference mine_ref = new MyInterface.mine.ByReference();   

因此,我调试代码,以便在Structure.class之后逐步进入JNA,进入以下getFields方法(在该方法中,我得到了异常(下面是第二个异常):

代码语言:javascript
运行
复制
    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方法中引发异常时所看到的以下字段值

代码语言:javascript
运行
复制
fieldOrder = [color, data, str, wild, hello, rice]
orderedNames = [str, color, data, hello, rice, wild]

引发异常是因为名称是空的。无论如何,由于HashSet java.util类不能保证随着时间的推移顺序将保持不变,所以我肯定认为JNA Structure.java中存在bug。因为我的字段顺序是通过new HashSet<String>(fieldOrder)指令随机排序的,因此不同于orderedNames的顺序。

  1. 是否有人同意我的观点,或者我是否遗漏了一些关于声明和使用JNA结构的方法?

如果没有bug,

  1. (即HashSet是故意使用的)我宣布我的结构有什么不对吗?我怎样才能解决这个问题?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-14 19:12:57

您的错误在mine结构中:您需要将字段声明为public。JNA使用反射,对于要映射到本机的字段依赖public修饰符;否则它们只是类中的助手字段。

否则,映射将以您拥有的方式工作,但请考虑以下改进:

  • 当作为嵌套结构使用时,不需要使用结构的ByValue版本。这是默认的。唯一需要使用嵌套结构的特殊操作是如果它是ByReference
    • 类似地,当用作函数参数时,ByReference是默认的。只有当函数需要ByValue参数时,才需要特殊的ByValue参数。

  • 在JNA5.x中用@FieldOrder注释替换了getFieldOrder()覆盖的使用。虽然您所拥有的可以工作,但是如果您只是将注释放在结构的前面,例如

,则代码的可读性更强。

代码语言:javascript
运行
复制
@FieldOrder({"data", "size"})
class his extends Structure { 
  // etc... 
}

默认情况下,

  • 接口变量/类/等是publicstaticfinal,因此使用这些修饰符是多余的。
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64835834

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档