Skip to content

Instantly share code, notes, and snippets.

@sgeos
Last active July 27, 2023 01:23
Show Gist options
  • Save sgeos/fa3f27e7504c4f17bbd644f14175fead to your computer and use it in GitHub Desktop.
Save sgeos/fa3f27e7504c4f17bbd644f14175fead to your computer and use it in GitHub Desktop.
no_std_rust_string_ffi_example.rs
#![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