Я пытаюсь взаимодействовать с API событий C, структурированным так:
struct EventA {
int type;
int data1;
int data2;
};
struct EventB {
int type;
int data1;
};
union Event {
int type;
EventA eventA;
EventB eventB;
};
//grabs the next event from the queue.
void pollEvent(Event *event);
В C API поле type
используется, чтобы определить, какой тип события произошел.По сути, это теговое объединение или перечисления в Rust.Я знаю, что Rust позволяет вам выбрать базовый тег перечисления с помощью #[repr(type)]
, однако я считаю, что Rust не гарантирует, что тег является первым полем перечисления.(Или это всегда последнее поле?) Это делает его довольно грубым при преобразовании API в Rust, потому что мне понадобится некоторый тип структуры-посредника для опроса, затем совпадения с его типом, преобразования его в перечисление, тогда пользователь будет соответствоватьENUM.
Если бы я знал, что тег был первым полем перечисления, я знаю, что перечисление и объединение имеют одно и то же представление памяти, и я мог бы просто передать его как указатель.
Что я хотел бы сделать:
use::std::os::raw::c_int;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct EventA {
pub data1: c_int,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct EventB {
pub data1: c_int,
pub data2: c_int,
}
#[repr(i32)] //I'm assuming c_int is 32 bit.
#[derive(Copy, Clone)]
pub enum Event {
// <---- Put the tag is here, followed the union memory,
A(EventA),
B(EventB),
}
extern {
pub fn pollEvents(*mut Event);
}
pub fn poll_events(*mut Event) {
unsafe {
pollEvents(*mut Event);
}
}