Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use C array in a Rust structure [duplicate]

Tags:

c

rust

ioctl

I'm programming a driver in rust and I have the following C struct which I need to convert to something equivalent in Rust:

struct vfio_irq_set {
    __u32   argsz;
    __u32   flags;
    __u32   index;
    __u32   start;
    __u32   count;
    __u8    data[];
};

The only variable that causes me some problems is the data array. So far I have the following rust structure:

#[allow(non_camel_case_types)]
#[repr(C)]
struct vfio_irq_set {
    argsz: u32,
    flags: u32,
    index: u32,
    start: u32,
    count: u32,
    data: *const u8,
}

The rust code to initialize the structure and make the ioctl call looks the following:

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());
}

But I always get back a "failed to VFIO_DEVICE_SET_IRQS. Errno: 22".

Does someone have an idea on what I'm doing wrong?

like image 422
tzwickl Avatar asked Aug 10 '26 00:08

tzwickl


1 Answers

In C, a struct whose last field is an array with no specified size is a dynamically typed struct. The data is present at the end of the struct with no extra level of indirection.

The Rust equivalent isn't a pointer (which has a fixed size), but a slice. Your struct would be in Rust:

#[allow(non_camel_case_types)]
#[repr(C)]
struct vfio_irq_set {
    argsz: u32,
    flags: u32,
    index: u32,
    start: u32,
    count: u32,
    data: [u8],
}

However those types are not really usable right now, and a more practical equivalent would be:

#[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,
}

where you have to make sure that T is a properly sized array or slice.

See also:

  • Dynamically Sized Types (DSTs) on the nomicon
like image 65
mcarton Avatar answered Aug 11 '26 15:08

mcarton



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!