【问题标题】:How to use C array in a Rust structure [duplicate]如何在 Rust 结构中使用 C 数组 [重复]
【发布时间】:2019-09-01 21:15:14
【问题描述】:

我正在用 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());
}

但我总是回复"failed to VFIO_DEVICE_SET_IRQS. Errno: 22"

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

【问题讨论】:

  • 他们不会有相同的布局。灵活的数据成员应该与结构的其余部分在连续的内存中,并且应该只占用存储数据所需的空间。你的例子没有这样做。指针总是占用空间,占用固定数量的空间,指向它的任何数据都不与结构的其余部分连续。
  • 另外,&amp;[event_fd as u8] as *const u8 可能不安全:该数组是临时的,寿命不够长。
  • 您还将丢失大小信息,因此即使数据不是临时的,也无法安全地读取该数据。
  • 是的,你说得对,这只是解决这个问题的绝望方法。我对 rust 很陌生,这是我以前从未见过的 :)

标签: c rust ioctl


【解决方案1】:

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

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

#[allow(non_camel_case_types)]
#[repr(C)]
struct vfio_irq_set {
    argsz: u32,
    flags: u32,
    index: u32,
    start: u32,
    count: u32,
    data: [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,
}

您必须确保T 是一个大小合适的数组或切片。

另见:

【讨论】:

  • 你觉得this question怎么样?它还没有答案。你认为这个问题应该被当作一个骗子来解决吗?你想移动你的答案吗?链接问题的 cmets 怎么样:它们是最新的吗?
  • @LukasKalbertodt 你似乎是对的。我回答了另一个问题,虽然我不能将这个问题设为重复,但我的答案还没有被投票。
  • @mcarton 非常感谢您的回复,这很有效 :) 我搜索了将近 2 个小时,但没有找到另一个,很抱歉在这里问了一个重复 :)
  • @tzwickl 不要担心重复询问!有一些其他问题具有与原始问题相关的不同表述总是很有用的。这样,人们可以更轻松地找到原始答案。
猜你喜欢
  • 2015-12-06
  • 2022-01-10
  • 2020-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-14
  • 1970-01-01
相关资源
最近更新 更多