1macro_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}