How to deal with lifetime when need to expose through FFI

The best thing then is to use an opaque type pattern:

#[repr(C)]
pub
struct FfiContext {
    _priv: [u8; 0],
    // Optional; to get the `Send` & `Sync` bounds right.
    _send_sync: ::core::marker::PhantomData<Context<'static, 'static>>,
);

#[no_mangle] pub extern "C"
fn init ()
  -> *mut FfiContext
{
    Box::into_raw(Box::new(Context::new()))
        .cast()
}

unsafe
fn from_ptr<'_0, '_1, '_2> (ptr: *mut FfiContext)
  -> &'_0 mut Context<'_1, '_2>
{
    if ptr.is_null() {
        eprintln!("Fatal error, got NULL `Context` pointer");
        ::std::process::abort();
    }
    &mut *(ptr.cast())
}

#[no_mangle] pub unsafe extern "C"
fn update (p: *mut FfiContext)
  -> u32
{
    let ctx: &'_ mut Context<'_, '_> = from_ptr(p);
    ctx.update(delta);
    0
}

#[no_mangle] pub unsafe extern "C"
fn free_context (p: *mut FfiContext)
{
    drop::<Box<Context<'_, '_>>>(Box::from_raw(from_ptr(p)))
}
3 Likes