Как отобразить объединение в структуре JNA - PullRequest
1 голос
/ 08 мая 2019

Мне нужно преобразовать пару структур C в Java, используя JNA.Мои структуры так сложены:

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:

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");
    }
}

Когда я использую метод

short xlReceive(long portHandle, IntByReference eventCount, s_xl_event eventList);

, я получаю значения, относящиеся ко всем полям в s_xl_event, за исключением tagData, где все поля заполнены0. Теперь я не уверен, что я отобразил все подструктуры и союзы, как ожидалось, или я что-то забыл.Кто-нибудь имел какое-либо отношение к такой вещи?

1 Ответ

0 голосов
/ 08 мая 2019

При чтении Union, например s_xl_tag_data, вы должны сообщить Union, какое из его полей читается, используя setType() с именем класса или поля, а затем вызвать read() для Union.

Один из способов сделать это автоматически при первом заполнении родительской структуры - переопределить метод read() в родительской структуре.

Добавьте этот метод в 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();
}

В качестве альтернативы передаче класса в setType() для элемента union вы можете вместо этого передать String, содержащийимя переменной, например, "msg", "chipState" или "linMsgApi" и т. д.

Также следует отметить, что методы getFieldOrder(), которые вы используете в Structure, устарели в последнихверсия JNA.Вместо этого вы должны использовать аннотацию @FieldOrder.

...