Different way to call into Rust from other languages

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"