Skip to content

Commit f83e73c

Browse files
committed
rust error callback
Rather then throw things directly, introduce a global callback. We will override the callback in workerd to integrate with kj::Exception
1 parent aeada50 commit f83e73c

File tree

4 files changed

+47
-5
lines changed

4 files changed

+47
-5
lines changed

gen/src/builtin.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -352,11 +352,11 @@ pub(super) fn write(out: &mut OutFile) {
352352
writeln!(out, "template <>");
353353
writeln!(out, "class impl<Error> final {{");
354354
writeln!(out, "public:");
355-
writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
355+
writeln!(out, " static void error(const char* msg, size_t len) {{");
356356
writeln!(out, " Error error;");
357-
writeln!(out, " error.msg = static_cast<char const *>(repr.ptr);");
358-
writeln!(out, " error.len = repr.len;");
359-
writeln!(out, " return error;");
357+
writeln!(out, " error.msg = msg;");
358+
writeln!(out, " error.len = len;");
359+
writeln!(out, " throw error;");
360360
writeln!(out, " }}");
361361
writeln!(out, "}};");
362362
}
@@ -395,6 +395,15 @@ pub(super) fn write(out: &mut OutFile) {
395395
}
396396

397397
out.end_block(Block::AnonymousNamespace);
398+
399+
if builtin.rust_error {
400+
out.next_section();
401+
writeln!(
402+
out,
403+
"inline void (*throw_rust_error)(const char*, size_t) = impl<Error>::error;"
404+
);
405+
}
406+
398407
out.end_block(Block::InlineNamespace("cxxbridge1"));
399408

400409
if builtin.trycatch {

gen/src/write.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,10 @@ fn write_rust_function_shim_impl(
11031103
writeln!(out, ";");
11041104
out.builtin.rust_error = true;
11051105
writeln!(out, " if (error$.ptr) {{");
1106-
writeln!(out, " throw ::rust::impl<::rust::Error>::error(error$);");
1106+
writeln!(
1107+
out,
1108+
" ::rust::throw_rust_error(static_cast<char const *>(error$.ptr), error$.len);"
1109+
);
11071110
writeln!(out, " }}");
11081111

11091112
if indirect_return {

include/cxx.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ template <typename T>
4242
class impl;
4343
}
4444

45+
// msg is 0-terminated, size counts the 0.
46+
// msg was new char[] allocated, ownership is transferred to throw_rust_error.
47+
extern void (*throw_rust_error)(const char* msg, size_t size);
48+
4549
#ifndef CXXBRIDGE1_RUST_STRING
4650
#define CXXBRIDGE1_RUST_STRING
4751
// https://cxx.rs/binding/string.html

tests/ffi/tests.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <array>
44
#include <cstdlib>
55
#include <cstring>
6+
#include <exception>
67
#include <iterator>
78
#include <memory>
89
#include <numeric>
@@ -761,6 +762,20 @@ std::unique_ptr<::F::F> c_return_ns_opaque_ptr() {
761762
return f;
762763
}
763764

765+
struct TestException : public std::exception {
766+
TestException(std::string&& msg) : message(std::move(msg)) {}
767+
768+
static void do_throw(const char* msg, size_t len) {
769+
throw TestException(std::string(msg, len));
770+
}
771+
772+
const char* what() const noexcept override {
773+
return message.c_str();
774+
}
775+
776+
std::string message;
777+
};
778+
764779
extern "C" const char *cxx_run_test() noexcept {
765780
#define STRINGIFY(x) #x
766781
#define TOSTRING(x) STRINGIFY(x)
@@ -987,6 +1002,17 @@ extern "C" const char *cxx_run_test() noexcept {
9871002
ASSERT(std::strcmp(e.what(), "panic in cxx_test_suite::ffi::r_panic: foobar") == 0);
9881003
}
9891004

1005+
// Test custom exception handler
1006+
auto prev_handler = ::rust::throw_rust_error;
1007+
::rust::throw_rust_error = TestException::do_throw;
1008+
try {
1009+
r_fail_return_primitive();
1010+
ASSERT(false);
1011+
} catch (const TestException &e) {
1012+
ASSERT(std::strcmp(e.what(), "rust error") == 0);
1013+
}
1014+
::rust::throw_rust_error = prev_handler;
1015+
9901016
cxx_test_suite_set_correct();
9911017
return nullptr;
9921018
}

0 commit comments

Comments
 (0)