use std::cell::Cell; use std::ffi::c_char; thread_local! { static CALLS: Cell = const { Cell::new(0) }; } #[unsafe(no_mangle)] pub extern "C" fn goose_init(_argc: i32, _argv: *mut *mut c_char) { CALLS.with(|calls| calls.set(100)); // this example's startup state only } /// Safety: length must point to a live, writable, aligned i64. #[unsafe(no_mangle)] pub unsafe extern "C" fn hello_world(length: *mut i64) -> *const u8 { CALLS.with(|calls| calls.set(calls.get() + 1)); const MESSAGE: &[u8] = b"Hello, world!"; unsafe { *length = MESSAGE.len() as i64; } MESSAGE.as_ptr() // static bytes, not NUL-terminated } #[unsafe(export_name = "c_add")] pub extern "C" fn add(a: i32, b: i32) -> i32 { a + b } fn main() { goose_init(0,std::ptr::null_mut()); let mut length=0_i64; // SAFETY: length is a valid writable local; the result is static MESSAGE bytes. let pointer=unsafe {hello_world(&mut length)}; let message=unsafe {std::slice::from_raw_parts(pointer,usize::try_from(length).unwrap())}; assert_eq!(message,b"Hello, world!");assert_eq!(CALLS.with(Cell::get),101); use std::io::Write;let mut out=std::io::stdout().lock();out.write_all(message).unwrap();writeln!(&mut out).unwrap(); writeln!(&mut out,"{}",add(20,22)).unwrap(); }