1 macro_rules! ffi_fn { 2 (fn $name:ident($($arg:ident: $arg_ty:ty),*,) -> $ret:ty $body:block) => { 3 ffi_fn!(fn $name($($arg: $arg_ty),*) -> $ret $body); 4 }; 5 (fn $name:ident($($arg:ident: $arg_ty:ty),*) -> $ret:ty $body:block) => { 6 #[no_mangle] 7 pub extern fn $name($($arg: $arg_ty),*) -> $ret { 8 use ::std::io::{self, Write}; 9 use ::std::panic::{self, AssertUnwindSafe}; 10 use ::libc::abort; 11 match panic::catch_unwind(AssertUnwindSafe(move || $body)) { 12 Ok(v) => v, 13 Err(err) => { 14 let msg = if let Some(&s) = err.downcast_ref::<&str>() { 15 s.to_owned() 16 } else if let Some(s) = err.downcast_ref::<String>() { 17 s.to_owned() 18 } else { 19 "UNABLE TO SHOW RESULT OF PANIC.".to_owned() 20 }; 21 let _ = writeln!( 22 &mut io::stderr(), 23 "panic unwind caught, aborting: {:?}", 24 msg); 25 unsafe { abort() } 26 } 27 } 28 } 29 }; 30 (fn $name:ident($($arg:ident: $arg_ty:ty),*,) $body:block) => { 31 ffi_fn!(fn $name($($arg: $arg_ty),*) -> () $body); 32 }; 33 (fn $name:ident($($arg:ident: $arg_ty:ty),*) $body:block) => { 34 ffi_fn!(fn $name($($arg: $arg_ty),*) -> () $body); 35 }; 36 } 37