首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在JNA结构中映射联合

如何在JNA结构中映射联合
EN

Stack Overflow用户
提问于 2019-05-08 23:12:45
回答 1查看 315关注 0票数 1

我需要使用JNA将一些C结构转换为java。我的结构是这样组成的:

代码语言:javascript
复制
struct s_xl_event {
XLeventTag tag;
unsigned char chanIndex;
unsigned short transId;
unsigned short portHandle;
unsigned char flags;
unsigned char reserved;
XLuint64 timeStamp;
union s_xl_tag_data tagData;
};

union s_xl_tag_data {
struct s_xl_can_msg msg;
struct s_xl_chip_state chipState;
union s_xl_lin_msg_api linMsgApi;
struct s_xl_sync_pulse syncPulse;
struct s_xl_daio_data daioData;
struct s_xl_transceiver transceiver;
};

struct s_xl_can_msg {
unsigned long id;
unsigned short flags;
unsigned short dlc;
XLuint64 res1;
unsigned char data[MAX_MSG_LEN];
XLuint64 res2;
};

我只添加了我需要的主结构,但也因为所有相关结构都类似于s_xl_can_msg

在Java中,我使用JNA做到了这一点:

代码语言:javascript
复制
public static class s_xl_event extends Structure {
    public byte tag;
    public byte chanIndex;
    public short transId;
    public short portHandle;
    public byte flags;
    public byte reserved;
    public long timeStamp;
    public s_xl_tag_data tagData;

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("tag","chanIndex","transId","portHandle","flags","reserved","timeStamp","tagData");
    }
}

public static class s_xl_tag_data extends Union {
    public s_xl_can_msg msg;
    public s_xl_chip_state chipState;
    public s_xl_lin_msg_api linMsgApi;
    public s_xl_sync_pulse syncPulse;
    public s_xl_daio_data daioData;
    public s_xl_transceiver transceiver;
}

public static class s_xl_lin_msg extends Structure {        
    public byte id;
    public byte dlc;
    public short flags;
    public byte[] data = new byte[8];
    public byte crc;

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("id","dlc","flags","data","crc");
    }
}

当我使用该方法时

代码语言:javascript
复制
short xlReceive(long portHandle, IntByReference eventCount, s_xl_event eventList);

我获得了与s_xl_event中除tagData之外的所有字段相关的值,其中所有字段都填充为0。现在,我不确定我是否像预期的那样映射了所有的子结构和联合,或者我忘记了什么。有没有人跟这件事有关?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-09 03:34:44

在读取像s_xl_tag_data这样的Union时,您必须通过使用带有类名或字段名的setType()来告诉Union正在读取它的哪个字段,然后在Union上调用read()

第一次填充父结构时自动执行此操作的一种方法是覆盖父结构中的read()方法。

将此方法添加到s_xl_event结构中:

代码语言:javascript
复制
public void read() {
    // read from native memory, populate tag
    super.read(); 
    // set union type based on tag
    switch(tag) {
    case XL_RECEIVE_MSG:
    case XL_TRANSMIT_MSG: 
        tagData.setType(s_xl_can_msg.class);
        break;
    case XL_CHIP_STATE: 
        tagData.setType(s_xl_chip_state.class);
        break;
    case XL_LIN_MSG: 
        tagData.setType(s_xl_lin_msg_api.class);
        break;
    // ... add other cases here...
    default:
        // add default type or throw exception etc.  
        break;
    }
    // now read tagData from native memory
    tagData.read();
}

作为将类传递给联合元素的setType()的替代方法,您可以传递一个包含变量名称的String,例如"msg""chipState""linMsgApi"等。

还要注意的是,您在Structure中使用的getFieldOrder()方法在最新版本的Structure中已弃用。您应该改用@FieldOrder注释。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56043874

复制
相关文章

相似问题

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