c - 由于内存布局,将标记的 C union 转换为 Rust 枚举时出现问题

标签 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 字段用于确定发生了什么类型的事件。这本质上是一个标记 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/

相关文章:

c - 有什么方法可以解决段错误吗?

rust - 如何使用 Rust 跟踪获取/存储跨度持续时间?

rust - 如何解释 Rust 中对可变类型的不可变引用?

floating-point - 是否可以在不添加小数点的情况下将 int 文字强制转换为 Rust 中的 float ?

objective-c - 将字符串添加到数组

c - C 中的链表访问冲突

web-scraping - 将输出(println!)转换为.csv文件

rust - 为什么普通匹配表达式可以编译,而 map_err 调用却不能?

c - 具有自动依赖关系的 Makefile

c - C输入带空格的字符串