Implement fallible Rust functions
diff --git a/gen/write.rs b/gen/write.rs
index d57e21e..ccb5a0f 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -271,7 +271,11 @@
 }
 
 fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    write_extern_return_type(out, &efn.ret, types);
+    if efn.throws {
+        write!(out, "::rust::Str::Repr ");
+    } else {
+        write_extern_return_type(out, &efn.ret, types);
+    }
     for name in out.namespace.clone() {
         write!(out, "{}$", name);
     }
@@ -305,7 +309,10 @@
         write_type_space(out, &arg.ty);
         write!(out, "{}", arg.ident);
     }
-    write!(out, ") noexcept");
+    write!(out, ")");
+    if !efn.throws {
+        write!(out, " noexcept");
+    }
     if out.header {
         writeln!(out, ";");
     } else {
@@ -339,6 +346,9 @@
                 _ => {}
             }
         }
+        if efn.throws {
+            write!(out, "::rust::Str::Repr error$ = ");
+        }
         for name in out.namespace.clone() {
             write!(out, "{}$", name);
         }
@@ -374,6 +384,11 @@
             }
         }
         writeln!(out, ";");
+        if efn.throws {
+            writeln!(out, "  if (error$.ptr) {{");
+            writeln!(out, "    throw ::rust::Error(error$);");
+            writeln!(out, "  }}");
+        }
         if indirect_return {
             writeln!(out, "  return ::std::move(return$.value);");
         }
@@ -391,7 +406,7 @@
 fn indirect_return(efn: &ExternFn, types: &Types) -> bool {
     efn.ret
         .as_ref()
-        .map_or(false, |ret| types.needs_indirect_abi(ret))
+        .map_or(false, |ret| efn.throws || types.needs_indirect_abi(ret))
 }
 
 fn write_extern_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types) {