+use std::ffi::{CStr, CString};
use std::os::raw;
/// Return The Answer.
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<T>(mut vec: Vec<T>) -> *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 {
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?"]);
+ }
}
int main()
{
+ const char *hello = "hello";
+ const char *haystack = "Hello\nworld\ncan you tell?";
+
printf("The answer: %i\n", answer());
+ printf("Length of '%s': %u\n", hello, r_strlen(hello));
+
+ const unsigned char **strs = r_strlist();
+ for (const unsigned char **s = strs; *s; s++)
+ printf("returned string array element: %s\n", *s);
+ free (strs);
+
+ const char **matches = r_grep("ell", "Hello\nworld\ncan you tell?");
+ for (const char **m = matches; *m; m++)
+ printf("matched line: %s\n", *m);
+ free (matches);
return 0;
}