Last active
July 27, 2023 01:23
-
-
Save sgeos/fa3f27e7504c4f17bbd644f14175fead to your computer and use it in GitHub Desktop.
no_std_rust_string_ffi_example.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![no_std] | |
extern crate alloc; | |
extern crate libc; | |
use alloc::{ boxed::Box, ffi::CString, string::{ String, ToString, } }; | |
use hashbrown::HashMap; | |
use libc::{ c_char, c_void, printf, }; | |
#[no_mangle] | |
pub extern "C" fn hashmap_new() -> *mut c_void { | |
let hashmap: HashMap<String, String> = HashMap::new(); | |
Box::into_raw(Box::new(hashmap)) as *mut c_void | |
} | |
#[no_mangle] | |
pub extern "C" fn hashmap_insert(hashmap_ptr: *mut c_void, key: *const c_char, value: *const c_char) { | |
let hashmap = unsafe { &mut *(hashmap_ptr as *mut HashMap<String, String>) }; | |
let key_str = unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts(key as *const u8, libc::strlen(key))) }; | |
let value_str = unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts(value as *const u8, libc::strlen(value))) }; | |
hashmap.insert(String::from(key_str), String::from(value_str)); | |
} | |
#[no_mangle] | |
pub extern "C" fn hashmap_get(hashmap_ptr: *mut c_void, key: *const c_char) -> *mut c_char { | |
let hashmap = unsafe { &mut *(hashmap_ptr as *mut HashMap<String, String>) }; | |
let key_str = unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts(key as *const u8, libc::strlen(key))) }; | |
match hashmap.get(key_str) { | |
Some(value) => { | |
let c_string = CString::new(value.as_str()).expect("Failed to create CString"); | |
c_string.into_raw() | |
}, | |
None => core::ptr::null_mut(), | |
} | |
} | |
#[no_mangle] | |
pub extern "C" fn hashmap_free(hashmap_ptr: *mut c_void) { | |
unsafe { | |
let _ = Box::from_raw(hashmap_ptr as *mut HashMap<String, String>); | |
} | |
} | |
#[no_mangle] | |
pub fn rust_string_to_c_string(s: String) -> *mut c_char { | |
let c_string = CString::new(s).expect("CString::new failed"); | |
c_string.into_raw() | |
} | |
#[no_mangle] | |
pub extern "C" fn free_c_string(s: *mut c_char) { | |
unsafe { | |
if s.is_null() { | |
return; | |
} | |
let _ = CString::from_raw(s); | |
} | |
} | |
pub fn print_c_string(c_string: *const c_char) { | |
unsafe { | |
printf(b"%s\n\0".as_ptr() as *const _, c_string); | |
} | |
} | |
fn main() { | |
let hashmap = hashmap_new(); | |
let key = rust_string_to_c_string("key".to_string()); | |
let value = rust_string_to_c_string("value".to_string()); | |
hashmap_insert(hashmap, key, value); | |
let returned_value = hashmap_get(hashmap, key); | |
print_c_string(returned_value); | |
hashmap_free(hashmap); | |
free_c_string(key); | |
free_c_string(value); | |
free_c_string(returned_value); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment