Skip to content

Instantly share code, notes, and snippets.

@divi255
Last active August 22, 2021 23:50
Show Gist options
  • Save divi255/d4d17ab3a2918358b77f5918ab375ff9 to your computer and use it in GitHub Desktop.
Save divi255/d4d17ab3a2918358b77f5918ab375ff9 to your computer and use it in GitHub Desktop.
Rust example: load a shared library and allow it to call the main process functions
/*
shared lib with safe calls, for std
put in Cargo.toml
[lib]
name = "test"
crate-type = [ "cdylib" ]
*/
use std::cell::RefCell;
fn dummy_mutiplier() -> u32 {
panic!("multiplier not registered");
}
struct Imports {
get_multiplier: Box<dyn Fn() -> u32>,
}
impl Imports {
fn new() -> Self {
Self {
get_multiplier: Box::new(dummy_mutiplier),
}
}
}
thread_local! {
static M: RefCell<Imports> = RefCell::new(Imports::new());
}
#[no_mangle]
pub fn register_multiplier(f: Box<dyn Fn() -> u32>) {
M.with(|m| {
m.borrow_mut().get_multiplier = f;
});
}
#[no_mangle]
pub fn testm(a: u32) -> u32 {
a * M.with(|m| (m.borrow().get_multiplier)())
}
/*
shared lib with unsafe calls, for nostd
put in Cargo.toml
[lib]
name = "test"
crate-type = [ "cdylib" ]
*/
fn dummy_mutiplier() -> u32 {
panic!("multiplier not registered");
}
static mut M: &dyn Fn() -> u32 = &dummy_mutiplier;
#[no_mangle]
pub fn register_multiplier(f: &'static dyn Fn() -> u32) {
unsafe {
M = f;
}
}
#[no_mangle]
pub fn testm(a: u32) -> u32 {
unsafe { a * M() }
}
use libloading::{Library, Symbol};
type MFunc = fn(u32) -> u32;
type RegisterMultiplierFunc = fn(&dyn Fn() -> u32); // may be wrapped with Box
fn get_multiplier() -> u32 {
4
}
fn main() {
let library_path = "/path/to/libtest.so";
let lib = unsafe { Library::new(library_path) }.unwrap();
let register_m: Symbol<RegisterMultiplierFunc> =
unsafe { lib.get(b"register_multiplier") }.unwrap();
register_m(&get_multiplier);
let testm: Symbol<MFunc> = unsafe { lib.get(b"testm") }.unwrap();
dbg!(testm(8));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment