fn shutdown(&self) -> std::result::Result<(), {{ core_import }}::{{ error_type }}> {
let Some(fp) = self.vtable.shutdown_fn else { return Ok(()); };
let mut _out_error: *mut std::ffi::c_char = std::ptr::null_mut();
// SAFETY: fp is valid; user_data validity is the caller's responsibility.
let rc = unsafe { fp(self.user_data, &mut _out_error) };
if rc != 0 {
let msg = if _out_error.is_null() { format!("shutdown returned {}", rc) } else {
// SAFETY: _out_error is a callee-allocated NUL-terminated string.
let msg = unsafe { std::ffi::CStr::from_ptr(_out_error) }.to_string_lossy().into_owned();
if let Some(free_fn) = self.vtable.free_string {
// SAFETY: free_fn is the vtable-provided destructor for callback strings.
unsafe { free_fn(_out_error) };
}
msg
};
return Err({{ plugin_error_expr | safe }});
}
Ok(())
}
}