Implement fallible Rust functions
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index fcfa1d9..defa565 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -136,7 +136,7 @@
     });
     let ret = expand_extern_return_type(&efn.ret, types);
     let mut outparam = None;
-    if indirect_return(&efn.ret, types) {
+    if indirect_return(efn, types) {
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
     }
@@ -154,7 +154,7 @@
     let decl = expand_cxx_function_decl(namespace, efn, types);
     let args = &efn.args;
     let ret = expand_return_type(&efn.ret);
-    let indirect_return = indirect_return(&efn.ret, types);
+    let indirect_return = indirect_return(efn, types);
     let vars = efn.args.iter().map(|arg| {
         let var = &arg.ident;
         match &arg.ty {
@@ -267,9 +267,7 @@
         }
     });
     let mut outparam = None;
-    let call = quote! {
-        ::cxx::private::catch_unwind(__fn, move || super::#ident(#(#vars),*))
-    };
+    let call = quote!(super::#ident(#(#vars),*));
     let mut expr = efn
         .ret
         .as_ref()
@@ -289,12 +287,22 @@
             _ => None,
         })
         .unwrap_or(call);
-    if indirect_return(&efn.ret, types) {
+    let indirect_return = indirect_return(efn, types);
+    if indirect_return {
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
+    }
+    if efn.throws {
+        expr = quote!(::cxx::private::r#try(__return, #expr));
+    } else if indirect_return {
         expr = quote!(::std::ptr::write(__return, #expr));
     }
-    let ret = expand_extern_return_type(&efn.ret, types);
+    expr = quote!(::cxx::private::catch_unwind(__fn, move || #expr));
+    let ret = if efn.throws {
+        quote!(-> ::std::option::Option<::cxx::private::RustStr>)
+    } else {
+        expand_extern_return_type(&efn.ret, types)
+    };
     let link_name = format!("{}cxxbridge02${}", namespace, ident);
     let local_name = format_ident!("__{}", ident);
     let catch_unwind_label = format!("::{}", ident);
@@ -407,9 +415,10 @@
     }
 }
 
-fn indirect_return(ret: &Option<Type>, types: &Types) -> bool {
-    ret.as_ref()
-        .map_or(false, |ret| types.needs_indirect_abi(ret))
+fn indirect_return(efn: &ExternFn, types: &Types) -> bool {
+    efn.ret
+        .as_ref()
+        .map_or(false, |ret| efn.throws || types.needs_indirect_abi(ret))
 }
 
 fn expand_extern_type(ty: &Type) -> TokenStream {