I think you may need to be more careful about alignment, especially on the C side.
I think transmute
by value itself is fine, and it should be forgiving about alignment, but if you return something to C by value, then C will have no way of knowing what is the right alignment for the type. Rust types can have a custom alignment greater than 8. When a struct stored on the C side is then returned to the Rust side by reference, you may get an unaligned pointer.
std::mem::drop
is not Drop::drop
. Calling std::mem::drop(&x)
is always a no-op, because std::mem::drop
is literally this:
fn drop<T>(meh: T) {}
and it drops by moving the value inside the function, where it becomes unused. But &
prevents moves, so nothing is moved, and nothing is dropped.
You can't, and don't need to to call Drop::drop
directly. It will always be called when an owned value goes out of scope, even if you create such value via transmute
. So C needs to be dropping "by value".
If you'd rather pass pointers around, you'd need to use Box::new() + Box::into_raw()
to create a pointer, and Box::from_raw()
to drop it. Cast to &
or &mut
to use without dropping.
As long as the same Rust measures and casts all these structs it should be fine, but the ABI is still technically unspecified. In nightly Rust there's a chaos monkey for this:
RUSTFLAGS="-Z randomize-layout"