-
Notifications
You must be signed in to change notification settings - Fork 18
Description
IIUC, you can pass mozjpeg a function that gets called when an error happens. That function currently panic!
. Is that the only source of panics from Rust callbacks ?
If so, it would be easy to change that into a C++ function that calls some Rust function and then throws some C++ exception containing whatever information would be interesting for Rust code (e.g. an error string):
extern "C" ErrorType error_function_rust();
extern "C" void error_function_cpp() {
ErrorType e = error_function_rust();
if (ErrorType.error()) { throw e.exception(); }
}
Otherwise, we could provide a small proc macro that does this automatically.
To catch that exception before unwinding into Rust and invoking UB, we would need to write one wrapper per extern "C"
function declaration in the library, with one or two exceptions.
It wouldn't be hard to write a small proc macro that does this automatically. You'd just put it in the top-level of the crate #![try_catch_extern_decls]
. This proc macro would do two things. First, for all functions within a extern "C" { ... }
block. It would change a function like:
extern "C" {
pub fn jpeg_destroy_compress(cinfo: &mut jpeg_compress_struct);
}
into:
pub unsafe fn jpeg_destroy_compress(cinfo: &mut jpeg_compress_struct) {
extern "C" {
pub fn jpeg_destroy_compress_rust_shim(cinfo: &mut jpeg_compress_struct) -> ErrorType;
}
if let Some(string) = jpeg_destroy_compress_rust_shim(cinfo) {
panic!(string)
}
}
These functions map an optional error message received from C into a Rust panic. Most functions in the jpeg API don't have a return type, so we can use that, but we could also use an out parameter.
Simultaneously, the proc macro would generate a rust_shim.cpp
file containing the Rust shims:
extern "C" CErrorType jpeg_destroy_compress_rust_shim(jpeg_compress_struct* cinfo) {
try {
jpeg_destroy_compress(cinfo);
return CErrorType::ok();
} catch (const runtime_error& e) {
return CErrorType::error(e);
}
}
We'd compile this shim using the cc
crate and link it on the fly to the current crate.