如何在锈蚀结构中使用C数组

如何在锈蚀结构中使用C数组,c,rust,ioctl,C,Rust,Ioctl,我正在用rust编写一个驱动程序,我有以下C结构,我需要将其转换为rust中的等价物: struct vfio_irq_set { __u32 argsz; __u32 flags; __u32 index; __u32 start; __u32 count; __u8 data[]; }; 唯一引起我一些问题的变量是数据数组。到目前为止,我有以下防锈结构: #[allow(non_camel_case_types)]

我正在用rust编写一个驱动程序,我有以下C结构,我需要将其转换为rust中的等价物:

struct vfio_irq_set {
    __u32   argsz;
    __u32   flags;
    __u32   index;
    __u32   start;
    __u32   count;
    __u8    data[];
};
唯一引起我一些问题的变量是数据数组。到目前为止,我有以下防锈结构:

#[allow(non_camel_case_types)]
#[repr(C)]
struct vfio_irq_set {
    argsz: u32,
    flags: u32,
    index: u32,
    start: u32,
    count: u32,
    data: *const u8,
}
初始化结构并进行
ioctl
调用的rust代码如下所示:

let irq_set: vfio_irq_set = vfio_irq_set {
    argsz: (mem::size_of::<vfio_irq_set>() + mem::size_of::<RawFd>() * (MAX_INTERRUPT_VECTORS + 1) as usize) as u32,
    count: interrupt_vector,
    flags: VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER,
    index: VFIO_PCI_MSIX_IRQ_INDEX as u32,
    start: 0,
    data: &[event_fd as u8] as *const u8,
};

if unsafe { libc::ioctl(device_fd, VFIO_DEVICE_SET_IRQS, &irq_set) } == -1 {
    return Err(format!(
        "failed to VFIO_DEVICE_SET_IRQS. Errno: {}",
        unsafe { *libc::__errno_location() }
    ).into());
}
设置irq\u:vfio\u irq\u set=vfio\u irq\u set{
argsz:(mem::size_of::()+mem::size_of::()*(MAX_INTERRUPT_VECTORS+1)as usize)as u32,
计数:中断向量,
标志:VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER,
索引:VFIO_PCI_MSIX_IRQ_索引为u32,
起点:0,
数据:&[event_fd as u8]as*const u8,
};
如果不安全{libc::ioctl(device_fd,VFIO_device_SET_IRQS,&irq_SET)}=-1{
返回错误(格式(
“无法VFIO_DEVICE_SET_IRQS.Errno:{}”,
不安全的{*libc::_errno_location()}
).into());
}
但我总是收到一个
“无法设置VFIO\u设备\u IRQS.Errno:22”


有人知道我做错了什么吗?

在C中,最后一个字段是没有指定大小的数组的结构是动态类型的结构。数据显示在结构的末尾,没有额外的间接层

Rust等价物不是指针(具有固定大小),而是切片。您的结构将生锈:

#[允许(非驼峰类型)]
#[报告员(C)]
结构vfio\u irq\u集{
argsz:u32,
国旗:u32,
索引:u32,
起点:u32,
计数:u32,
数据:[u8],
}
但是,这些类型目前还不能真正使用,更实用的等效方法是:

#[allow(non_camel_case_types)]
#[repr(C)]
struct vfio_irq_set<T: ?Sized> {
    argsz: u32,
    flags: u32,
    index: u32,
    start: u32,
    count: u32,
    data: T,
}
#[允许(非驼峰类型)]
#[报告员(C)]
结构vfio\u irq\u集{
argsz:u32,
国旗:u32,
索引:u32,
起点:u32,
计数:u32,
数据:T,
}
您必须确保
T
是大小适当的数组或片

另见:


它们不会有相同的布局。灵活的数据成员应该与结构的其余部分在连续内存中,并且应该只占用存储数据所需的空间。你的例子没有做到这一点。指针总是占用空间,占用固定的空间量,指向它的任何数据都与结构的其余部分不连续。此外,
&[event\u fd as u8]as*const u8
可能不安全:数组是临时的,寿命不够长。您还将丢失大小信息,所以即使数据不是临时的,它也无法安全地读取数据。是的,你们都是对的,这只是解决这个问题的一种不顾一切的方法。我对生锈还很陌生,这是我以前从未见过的:)你觉得怎么样?它还没有答案。你认为这个问题应该作为一个骗局来解决吗?那么你想移动你的答案吗?链接问题的评论如何:它们是最新的吗?@LukasKalbertodt你似乎是对的。我回答了另一个问题,虽然我还不能把这个问题复制出来,因为我的答案还没有被提升。@mcarton非常感谢你的回答,这个问题成功了:)我搜索了将近2个小时,但没有找到另一个问题,所以很抱歉在这里问了一个副本:)@tzwickl不要担心问重复的问题!有几个其他的问题,用不同的公式和原始问题联系起来,总是很有用的。这样,人们可以更容易地找到原始答案。