Skip to main content

Module handle

Module handle 

Source
Expand description

Opaque handle helpers for boxing/unboxing Rust plugin state behind the type-erased *mut c_void plugin contract.

Confium plugins expose their per-instance state through opaque pointers (e.g. *mut FFIHash). The loader never inspects the pointee — it just hands the pointer back to the plugin on every call. Conventionally a plugin author writes Box::into_raw(Box::new(state)) as *mut c_void in create and Box::from_raw(ptr) in destroy, sprinkling unsafe through their code.

OpaqueHandle wraps that pattern so plugin authors can stay in safe Rust for the lifetime of the handle:

use confium_api::OpaqueHandle;

// `create` returns an opaque pointer the loader will hand back.
fn create() -> *mut std::ffi::c_void {
    let state = MyHash { buf: Vec::new() };
    OpaqueHandle::<MyHash>::new(state)
}

// Every other entry point borrows the live state.
unsafe fn update(ptr: *mut std::ffi::c_void, data: &[u8]) {
    let handle = OpaqueHandle::<MyHash>::borrow_raw(ptr);
    handle.buf.extend_from_slice(data);
}

// `destroy` reclaims ownership and drops the state.
unsafe fn destroy(ptr: *mut std::ffi::c_void) {
    let _ = OpaqueHandle::<MyHash>::from_raw(ptr);
}

§Safety contract

The pointer returned by OpaqueHandle::into_raw is owned by the caller (typically the Confium loader) until the matching destroy symbol is invoked. Borrowing it from any other thread, or calling from_raw more than once, is undefined behavior. Plugins are single-threaded with respect to a given instance handle in the v0 contract.

Structs§

OpaqueHandle
Wrapper around a Box<T> that knows how to round-trip through a raw *mut c_void pointer without exposing unsafe at call sites.