Function ffi_support::call_with_result[][src]

pub fn call_with_result<R, E, F>(
    out_error: &mut ExternError,
    callback: F
) -> R::Value where
    F: UnwindSafe + FnOnce() -> Result<R, E>,
    E: Into<ExternError>,
    R: IntoFfi
Expand description

Call a callback that returns a Result<T, E> while:

  • Catching panics, and reporting them to C via ExternError.
  • Converting T to a C-compatible type using IntoFfi.
  • Converting E to a C-compatible error via Into<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(())
    })
}