In a mixture of Rust and C code for a microcontroller, I have a Rust data structure that I have to make known to the C part of my program. I got this working.
pub struct SerialPort {
// ... some attributes ...
}
I tried to refactor the Rust code and wanted to generate the Rust structure in a function that also registers the callbacks in my C Code.
pub fn setup_new_port() -> SerialPort {
let port = SerialPort::new();
port.register_with_c_code();
port
}
This doesn't work because Rust will move the content of the memory of my variable of type SerialPort
to a different location when the function returns. The addresses registered in the C code point to the (now freed) stackframe of setup_new_port()
while it got moved to the stack frame of the caller, so my C code will access invalid addresses.
Is there any trait that I can implement that gets notified when a move happens? I could adjust the addresses registered in my C code in the implementation of the trait.
I know that I could prevent the move from happening by allocating my structure on the heap, but I would like to avoid this as the code runs on a microcontroller and dynamic memory allocation might not always be present.
No, by design.
Rust was specifically designed without so-called move constructors, in Rust a move is a bitwise copy, allowing many optimizations:
memcpy
and realloc
,panic!
can be called during a move,Actually, there are proposals in C++ to retrofit such a design (is_relocatable
), and performance is the main driver.
So what?
Do it like Mutex
do! That is, Box
whatever should not move, and isolate it in an opaque struct
so that nobody can move the content out of the box.
If heap allocation is not available... then you may want to look into PinMut
, or otherwise borrow the structure. What is borrowed cannot be moved.