/// Register a C plugin implementing `{{ trait_name }}` via a vtable.
///
/// # Parameters
///
/// - `name`: null-terminated UTF-8 plugin name. Must not be null.
/// - `vtable`: vtable with function pointers implementing the trait.
/// - `user_data`: opaque pointer forwarded to every vtable function.
/// - `out_error`: receives a heap-allocated error string on failure.
///
/// # Safety
///
/// All function pointers in `vtable` must remain valid until the plugin is
/// unregistered. `user_data` must be safe to use from any thread that calls
/// into the plugin.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn {{ full_register_name }}(
name: *const std::ffi::c_char,
vtable: *const {{ vtable_name }},
user_data: *const std::ffi::c_void,
out_error: *mut *mut std::ffi::c_char,
) -> i32 {
if name.is_null() {
// SAFETY: out_error is validated by ffi_set_out_error itself (null-checked internally).
unsafe { ffi_set_out_error(out_error, "name must not be null") };
return 1;
}
if vtable.is_null() {
// SAFETY: out_error is validated by ffi_set_out_error itself (null-checked internally).
unsafe { ffi_set_out_error(out_error, "vtable must not be null") };
return 1;
}
// SAFETY: null check above guarantees vtable is a valid pointer.
let vtable_ref = unsafe { &*vtable };
if vtable_ref.free_string.is_none() {
// SAFETY: out_error is validated by ffi_set_out_error itself (null-checked internally).
unsafe { ffi_set_out_error(out_error, "vtable.free_string must not be null") };
return 1;
}