use enum_dispatch::enum_dispatch; type Function<'a> = unsafe extern "C" fn(&'a [u8]); type HackyClosure<'a> = (Function<'a>, &'a [u8]); #[enum_dispatch] trait Execute : Sized{ fn execute(&self); fn get_exec<'a>(&'a self) -> HackyClosure { let f = execute_from_c::; let ptr = self as *const Self as *const u8; let slice = unsafe{core::slice::from_raw_parts(ptr, core::mem::size_of_val(self))}; return (f, slice); } } struct Hallo{name: String} impl Execute for Hallo { fn execute(&self) { println!("Hallo {}", self.name); } } struct Bla{b: u8} impl Execute for Bla { fn execute(&self) { println!("Bla: {}", self.b); } } #[enum_dispatch(Execute)] enum Instruction { Bla, Hallo } unsafe extern "C" fn execute_from_c(c_self: &[u8]) { (*(c_self.as_ptr() as *const I)).execute(); } fn main() { let ins1 : Instruction= Bla{b: 3}.into(); ins1.execute(); let ins2 : Instruction= Hallo{name: "du da".into()}.into(); ins2.execute(); dbg!(ins1.get_exec()); dbg!(ins2.get_exec()); unsafe{ let (f,a) = ins1.get_exec(); callit(f, a); } unsafe{ let (f,a) = ins2.get_exec(); callit(f, a); } let x = callit; dbg!(std::ptr::addr_of!(x)); } pub unsafe extern "C" fn callit<'a>(f: Function<'a>, a: &'a[u8]) { f(a); }