rust-lang / rust-lang/rust-bindgen
Support C++ exceptions without undefined behaviour
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 5.3k
- Forks
- 829
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 15
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 https://github.com/rust-lang-nursery/rust-bindgen/issues/1172#issuecomment-354831001 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)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the proposed C++ wrapper design in this issue and the linked rust-bindgen issue 1172. Work out how wrapper generation, exception-to-result handling, and the additional C++ build requirement would fit together; done means C++ exceptions cannot unwind into Rust and the design's compatibility trade-offs are resolved.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, rust
- Domain
- compilers, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100