[英]How to map a union in a JNA Structure
I need to convert a couple C structures to java using JNA. 我需要使用JNA将几个C结构转换为Java。 My structures are so composed:
我的结构是如此组成:
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;
};
I added only the main structures that I needed but also because all the related structure are similar to s_xl_can_msg
. 我仅添加了我需要的主要结构,还因为所有相关结构都与
s_xl_can_msg
相似。
In Java I did this using JNA: 在Java中,我使用JNA做到了这一点:
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");
}
}
When I use the method 当我使用方法
short xlReceive(long portHandle, IntByReference eventCount, s_xl_event eventList);
I obtain the values related to all the fields in s_xl_event
except for tagData
where all the fields are filled with 0. Now, I'm not sure that I mapped all the sub structures and unions as expected or I forgot something. 我获得了与
tagData
中所有字段相关的值,除了s_xl_event
之外,其中所有字段均填充为0。 Has anyone had anything to do with such a thing? 有没有人与这样的事情有关?
When reading a Union
like s_xl_tag_data
, you must tell the Union which of its fields is being read by using setType()
with either the class or field name, and then call read()
on the Union. 当读取一个
Union
像s_xl_tag_data
,你必须告诉联盟的哪个领域正通过读取setType()
与任一类或字段名称,然后调用read()
在联盟。
One way of doing this automatically when the parent structure is first populated is by overriding the read()
method in the parent structure. 第一次填充父结构时自动执行此操作的一种方法是,重写父结构中的
read()
方法。
Add this method to your s_xl_event
Structure: 将此方法添加到您的
s_xl_event
结构中:
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();
}
As an alternative to passing the class to setType()
for the union element, you could instead pass a String
containing the variable name, eg, "msg"
, "chipState"
, or "linMsgApi"
, etc. 作为将类传递给union元素的
setType()
的替代方法,您可以传递包含变量名称的String
,例如"msg"
, "chipState"
或"linMsgApi"
等。
Also of note, the getFieldOrder()
methods you are using in your Structure
s are deprecated in the latest version of JNA. 还要注意,在最新版本的JNA中,不赞成在
Structure
中使用的getFieldOrder()
方法。 You should use the @FieldOrder
annotation instead. 您应该改用
@FieldOrder
批注。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.