Result<T>
Result<T> is allowed as the return type of an extern function in either direction. Its behavior is to translate to/from C++ exceptions. If your codebase does not use C++ exceptions, or prefers to represent fallibility using something like outcome<T>, leaf::result<T>, StatusOr<T>, etc then you'll need to handle the translation of those to Rust Result<T> using your own shims for now. Better support for this is planned.
If an exception is thrown from an extern "C++"
function that is not declared
by the CXX bridge to return Result, the program calls C++'s std::terminate
.
The behavior is equivalent to the same exception being thrown through a
noexcept
C++ function.
If a panic occurs in any extern "Rust"
function, regardless of whether it is
declared by the CXX bridge to return Result, a message is logged and the program
calls Rust's std::process::abort
.
Returning Result from Rust to C++
An extern "Rust"
function returning a Result turns into a throw
in C++ if
the Rust side produces an error.
Note that the return type written inside of cxx::bridge must be written without a second type parameter. Only the Ok type is specified for the purpose of the FFI. The Rust implementation (outside of the bridge module) may pick any error type as long as it has a std::fmt::Display impl.
The exception that gets thrown by CXX on the C++ side is always of type
rust::Error
and has the following C++ public API. The what()
member function
gives the error message according to the Rust error's std::fmt::Display impl.
Returning Result from C++ to Rust
An extern "C++"
function returning a Result turns into a catch
in C++ that
converts the exception into an Err for Rust.
Note that the return type written inside of cxx::bridge must be written without
a second type parameter. Only the Ok type is specified for the purpose of the
FFI. The resulting error type created by CXX when an extern "C++"
function
throws will always be of type cxx::Exception
.
The specific set of caught exceptions and the conversion to error message are
both customizable. The way you do this is by defining a template function
rust::behavior::trycatch
with a suitable signature inside any one of the
headers include!
'd by your cxx::bridge.
The template signature is required to be:
The default trycatch
used by CXX if you have not provided your own is the
following. You must follow the same pattern: invoke func
with no arguments,
catch whatever exception(s) you want, and invoke fail
with the error message
you'd like for the Rust error to have.