c - 由于内存布局,将标记的 C 联合转换为 Rust 枚举的问题
问题描述
我正在尝试与结构如下的 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
字段用于确定发生了什么类型的事件。这本质上是一个标记的联合,或者 Rust 中的枚举。我知道 Rust 允许你选择枚举的底层标签,#[repr(type)]
但是我相信 Rust 不能保证标签是枚举的第一个字段。(或者它总是最后一个字段?)这使得将 API 转换为 Rust 时有点恶心,因为我需要某种类型的中间人结构来轮询然后匹配其类型,将其转换为枚举,然后用户将匹配枚举。
如果我知道标签是枚举的第一个字段,我知道枚举和联合具有相同的内存表示,我可以将它作为指针传递。
我想做的事:
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 只做最好的猜测,您应该在编译时添加内存布局测试。
推荐阅读
- jquery - jquery slideToggle 不会回到原始设置
- ios - 如何解决问题?我在正文中给出了描述
- javascript - 将 Android 或 IOS 上的套接字连接到 Sails js
- bash - 从终端执行 python 脚本,从文件夹读取输入文件并将输出文件写入另一个文件夹
- azure - Azure 逻辑应用 - 根据已启动的运行禁用/限制
- scala - ScalaTest:是否可以结合 AsyncWordSpec 和 GuiceOneAppPerSuite
- i3 - 如何按特定顺序自动启动程序?
- javascript - 我不知道为什么,但我的 ajax POST 方法没有返回任何响应
- database - 从 sqlite3 INNER JOIN 一无所获
- vue.js - nuxt js路由器没有将数据道具从一个组件传递到另一个组件