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.