我正在尝试与结构如下的 C 事件 API 进行交互:
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
字段用于确定发生了什么类型的事件。这本质上是一个标记 union ,或者 Rust 中的枚举。我知道 Rust 允许您使用 #[repr(type)]
选择枚举的基础标签,但我相信 Rust 不保证该标签是枚举的第一个字段。 (或者它总是最后一个字段?)这在将 API 转换为 Rust 时有点恶心,因为我需要某种类型的中间人结构来轮询然后匹配其类型,将其转换为枚举,然后用户将匹配枚举。
如果我知道标记是枚举的第一个字段,我就知道枚举和 union 具有相同的内存表示,我可以将它作为指针传递。
我想做什么:
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);
}
}
最佳答案
有一个RFC当您在基本上允许您想要的枚举上使用 #[repr(C, Int)]
时,可以保证一些布局。请注意,与往常一样,Rust 只会做出最好的猜测,您应该在编译时添加内存布局测试。
关于c - 由于内存布局,将标记的 C union 转换为 Rust 枚举时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54428163/