use std::ffi::{CStr, CString}; use std::os::raw::c_char; // Symbols every module must export with `extern "C"` and `#[no_mangle]`. // Signature: fn module_name() -> *const c_char // Signature: fn module_invoke(op: *const c_char, payload: *const c_char) -> *mut c_char pub const SYMBOL_NAME: &str = "module_name"; pub const SYMBOL_INVOKE: &str = "module_invoke"; // Helper to convert C char* to &str pub unsafe fn cstr_to_str<'a>(ptr: *const c_char) -> anyhow::Result<&'a str> { if ptr.is_null() { anyhow::bail!("null pointer"); } Ok(CStr::from_ptr(ptr).to_str()?) } // Helper to allocate a CString for return across FFI boundary (module side) pub fn string_to_cstring_ptr(s: String) -> *mut c_char { CString::new(s).unwrap().into_raw() } // Helper to take back ownership of a CString (host side), then free by letting CString drop pub unsafe fn take_cstring(ptr: *mut c_char) -> anyhow::Result { if ptr.is_null() { anyhow::bail!("null pointer"); } let s = CString::from_raw(ptr); Ok(s.into_string()?) }