use std::ffi::{CStr, CString}; use std::os::raw; /// Return The Answer. /// /// # Example /// /// ``` /// let a = call_rust_from_c::answer(); /// assert_eq!(a, 42); /// ``` #[no_mangle] // C 'int'; it does not actually hurt to have more specific types such as int32_t, but it's good to know that plain ints work pub extern "C" fn answer() -> raw::c_int { return 42; } #[no_mangle] pub extern "C" fn r_strlen(s: *const raw::c_char) -> usize { unsafe { CStr::from_ptr(s) }.to_bytes().len() } /// Return a vector of pointers as C pointer array /// /// The memory of `vec` gets leaked, as otherwise Rust would free it once the vector /// goes out of scope, and C would access invalid memory. fn return_c_vec(mut vec: Vec) -> *mut T { let p = vec.as_mut_ptr(); // unref vector so that it does not get freed when going out of scope std::mem::forget(vec); p } #[no_mangle] pub extern "C" fn r_strlist() -> *mut *const raw::c_uchar { let v = vec![ "Hello\0".as_ptr(), "World\0".as_ptr() ]; return_c_vec(v) } fn impl_grep<'a>(needle: &str, haystack: &'a str) -> Vec<&'a str> { haystack.lines() .filter(|line| line.contains(needle)) .collect() } #[no_mangle] pub extern "C" fn r_grep(needle: *const raw::c_char, haystack: *const raw::c_char) -> *mut *const raw::c_char { let haystack_cstr = unsafe { CStr::from_ptr(haystack).to_str() }.unwrap(); let strvec = impl_grep(unsafe { CStr::from_ptr(needle).to_str().unwrap() }, haystack_cstr); // Vec[str] -> Vec[const char*] let p_vec: Vec<_> = strvec.into_iter() .map(|s| { let s = CString::new(s).unwrap(); let p = s.as_ptr(); std::mem::forget(s); p }) .collect(); return_c_vec(p_vec) } #[cfg(test)] mod tests { use super::*; #[test] fn test_answer() { assert_eq!(answer(), 42); } #[test] fn test_grep() { assert_eq!(impl_grep("ell", "Hello\nworld\ncan you tell?"), vec!["Hello", "can you tell?"]); } }