pub fn call_with_result<R, E, F>(
out_error: &mut ExternError,
callback: F,
) -> R::ValueExpand description
Call a callback that returns a Result<T, E> while:
- Catching panics, and reporting them to C via
ExternError. - Converting
Tto a C-compatible type usingIntoFfi. - Converting
Eto a C-compatible error viaInto<ExternError>.
This (or call_with_output) should be in the majority of the FFI functions, see the crate
top-level docs for more info.
If your function doesn’t produce an error, you may use call_with_output instead, which
doesn’t require you return a Result.
§Example
A few points about the following example:
-
We need to mark it as
#[no_mangle] pub extern "C". -
We prefix it with a unique name for the library (e.g.
mylib_). Foreign functions are not namespaced, and symbol collisions can cause a large number of problems and subtle bugs, including memory safety issues in some cases.
#[no_mangle]
pub extern "C" fn mylib_print_string(
// Strings come in as an `FfiStr`, which is a wrapper around a null terminated C string.
thing_to_print: FfiStr<'_>,
// Note that taking `&mut T` and `&T` is both allowed and encouraged, so long as `T: Sized`,
// (e.g. it can't be a trait object, `&[T]`, a `&str`, etc). Also note that `Option<&T>` and
// `Option<&mut T>` are also allowed, if you expect the caller to sometimes pass in null, but
// that's the only case when it's currently to use `Option` in an argument list like this).
error: &mut ExternError
) {
// You should try to to do as little as possible outside the call_with_result,
// to avoid a case where a panic occurs.
ffi_support::call_with_result(error, || {
let s = thing_to_print.as_str();
if s.is_empty() {
// This is a silly example!
return Err(BadEmptyString);
}
println!("{}", s);
Ok(())
})
}