Passing C struct by value to Rust

I have a program that populates a struct and then attempts to pass it by value to my Rust function. What I'm observing, via gdb, is that the Rust function appears to receive the struct (command) by ref, and not by value:

Breakpoint 7, hsms::hsms_run (state=0x0, command=..., handler=0x32f55 <on_app_evt>) at src/lib.rs:48

(gdb) x/8 &command
0x2003ff24:	0x02	0xfe	0x03	0x20	0x01	0x00	0x00	0x00

Given that the struct is 8 bytes long, I'm guessing that gcc (arm-gcc) is optimising the call to the static-lib-hosted Rust function. I can declare the struct to be passed by reference, but it'd be great to confirm what's going on and receive some advice.

Here's the C calling code:

Command command = {SetOutsideMovement, .set_outside_movement = {current_sensor_time}};
app_state = hsms_run(app_state, command, on_app_evt);

hsms_run is a Rust function declared as follows:

#[no_mangle]
pub extern "C" fn hsms_run(
    state: *mut c_void,
    command: Command,
    handler: extern "C" fn(Event),
) -> *mut c_void

Thanks for any help.

did you #[repr(C)] the struct Commad on the rust side?

Yes I did. Thanks

Not sure then. I'd pass by reference and copy it for now.

I arrived at the following solution:

#[repr(C, i32)]
pub enum Command {
    GetEntryExits,
    SetOutsideMovement { time: u32 },
...
}

...where my enum required i32 sizing. What I discovered was that a match expression within my Rust code jumped to an undesirable location causing a fault given that the enum wasn't interpreted correctly. Looking back at the original gdb inspection of the memory that I posted makes it look obvious now, but I suppose my assumption was that repr(C) was sufficient.

Note, I could have used u8 or u16 for sizing also. The EABI spec, "Enumerated Types" elaborates on this, and states that i32 should be generally preferred in order to remain portable, which is particularly fine given the general alignment of struct fields on 32-bit word boundaries.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.