Description
Bindgen currently does not (cannot) support C++ exceptions, because C++ won't be able to unwind correctly into the rust code.
An idea to support this would be to emit a C++ wrapper for the C++ functions (see #1172 (comment) for the design idea). Emitting a C++ wrapper for functions would also allow to (by making it extern "C") remove all of bindgen
's code for mangling C++ functions and make supporting new C++ compilers much easier.
A C++ wrapper function could look like this (syntax untested esp. the union one, and there are tricks with non-copyable return types, I can never remember the correct syntax for moving c++ stuff):
// Original function
ret_t fun(arg_t arg) {
// ...
}
// Wrapper function
struct XXX_bindgen_result_ret_t {
enum { OK, ERROR, UNKNOWN_ERROR } tag;
union {
ret_t ok;
char * error_msg;
} value;
static XXX_bindgen_result_ret_t make_ok(ret_t r) {
XXX_bindgen_result_ret_t ret;
ret.tag = OK;
ret.value.ok = r;
return ret;
}
static XXX_bindgen_result_ret_t make_err(char * s) {
XXX_bindgen_result_ret_t ret;
ret.tag = ERROR;
ret.value.error_msg = s;
return ret;
}
static XXX_bindgen_result_ret_t make_unknown_error() {
XXX_bindgen_result_ret_t ret;
ret.tag = UNKNOWN_ERROR;
return ret;
}
};
extern "C"
XXX_bindgen_result_ret_t XXX_bindgen_function_fun(arg_t arg) {
try {
return XXX_bindgen_result_ret_t::make_ok(original_cpp_function(arg));
} catch (exception e) {
return XXX_bindgen_result_ret_t::make_err(e.message());
} catch (...) {
return XXX_bindgen_result_ret_t::make_unknown_error();
}
}
Basically, with this C++ wrapper, bindgen
takes control of the way FFI is performed, and can almost ignore the fact that it's a C++ compiler on which it's running.
The drawbacks are:
- A (single) additional function call at each FFI call
- Requirement to build an additional C++ file in addition to building rust code
- This requirement is a backward-incompatible change if it's not hidden behind a flag (and I guess if exceptions are supported it should be by opt-out and not opt-in, unless not opting in also means not allowing C++, given it's such an easy way to trigger UB and exceptions are way too rarely documented)