Rust FFI Ownership Cheat Sheet

Shape safe boundaries when talking to C or other runtimes

Last Updated: November 21, 2025

Ownership Focus

Boundary Strategy
extern "C" entrypoints Return handles via Box::into_raw and wrap callbacks in safe helpers.
FFI-safe structs Mark with #[repr(C)] and hide Rust-only fields behind opaque pointers.
C strings Use CString::new(..) before as_ptr() and CString::from_raw() on the return.
Drop guards Implement Drop to close file descriptors before crossing the boundary.

Common Patterns

#[no_mangle] pub extern "C" fn create(ctx: *mut Context) -> *mut Handle
Export a stable entrypoint for foreign callers.
let handle = Box::into_raw(Box::new(Context::new()))
Give ownership of a heap value to the caller.
unsafe { *ctx = Context::from_raw(ptr) }
Rebuild safe references when foreign code returns.
impl Drop for Handle
Always close sockets or files before Rust drops the struct.

Summary

Declare ownership rules explicitly, keep unsafe localized, and favor safe wrappers so the FFI surface stays predictable.

💡 Pro Tip: Document who owns each pointer and drop handles before returning control to the other side.
← Back to Programming Languages | Browse all categories | View all cheat sheets