Implement fallible C++ functions
diff --git a/gen/write.rs b/gen/write.rs
index ccb5a0f..3398f9a 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -45,6 +45,7 @@
if !header {
out.begin_block("extern \"C\"");
+ write_exception_glue(out, apis);
for api in apis {
let (efn, write): (_, fn(_, _, _)) = match api {
Api::CxxFunction(efn) => (efn, write_cxx_function_shim),
@@ -186,8 +187,32 @@
writeln!(out, "using {} = {};", ident, ident);
}
+fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
+ let mut has_cxx_throws = false;
+ for api in apis {
+ if let Api::CxxFunction(efn) = api {
+ if efn.throws {
+ has_cxx_throws = true;
+ break;
+ }
+ }
+ }
+
+ if has_cxx_throws {
+ out.next_section();
+ write!(
+ out,
+ "const char *cxxbridge02$exception(const char *, size_t);",
+ );
+ }
+}
+
fn write_cxx_function_shim(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);
}
@@ -221,6 +246,11 @@
}
writeln!(out, ") = {};", efn.ident);
write!(out, " ");
+ if efn.throws {
+ writeln!(out, "::rust::Str::Repr throw$;");
+ writeln!(out, " try {{");
+ write!(out, " ");
+ }
if indirect_return {
write!(out, "new (return$) ");
write_type(out, efn.ret.as_ref().unwrap());
@@ -267,6 +297,19 @@
write!(out, ")");
}
writeln!(out, ";");
+ if efn.throws {
+ out.include.cstring = true;
+ writeln!(out, " throw$.ptr = nullptr;");
+ writeln!(out, " }} catch (const ::std::exception &catch$) {{");
+ writeln!(out, " const char *return$ = catch$.what();");
+ writeln!(out, " throw$.len = ::std::strlen(return$);");
+ writeln!(
+ out,
+ " throw$.ptr = cxxbridge02$exception(return$, throw$.len);",
+ );
+ writeln!(out, " }}");
+ writeln!(out, " return throw$;");
+ }
writeln!(out, "}}");
}