如何在 Rust 结构中使用 C 数组
How to use C array in a Rust structure
我正在用 Rust 编写驱动程序,我有以下 C 结构,我需要将其转换为 Rust 中的等效结构:
struct vfio_irq_set {
__u32 argsz;
__u32 flags;
__u32 index;
__u32 start;
__u32 count;
__u8 data[];
};
给我带来一些问题的唯一变量是数据数组。到目前为止,我有以下 rust 结构:
#[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"
。
有人知道我做错了什么吗?
在 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
是大小合适的数组或切片。
另请参阅:
我正在用 Rust 编写驱动程序,我有以下 C 结构,我需要将其转换为 Rust 中的等效结构:
struct vfio_irq_set {
__u32 argsz;
__u32 flags;
__u32 index;
__u32 start;
__u32 count;
__u8 data[];
};
给我带来一些问题的唯一变量是数据数组。到目前为止,我有以下 rust 结构:
#[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"
。
有人知道我做错了什么吗?
在 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
是大小合适的数组或切片。
另请参阅: