Patterns

Patterns are higher-level abstractions for common interop scenarios. They can generally be used in both forward and reverse interop scenarios, although not all patterns are supported everywhere. Check the #[ffi] / plugin!() API documentation for the latest details.

Slices

Borrow contiguous data across the FFI boundary without copying.

#[ffi]
pub fn pattern_ffi_slice(slice: ffi::Slice<u32>) -> u32 {
    slice.as_slice().len() as u32
}

#[ffi]
pub fn pattern_ffi_slice_mut(mut slice: ffi::SliceMut<u8>, callback: CallbackSliceMut) {
    if let [x, ..] = slice.as_slice_mut() { *x += 1; }
    callback.call(slice);
}

Option

Nullable values.

#[ffi]
pub fn pattern_ffi_option(x: ffi::Option<Inner>) -> ffi::Option<Inner> { x }

Note, this refers to the ffi::Option type. We also support std::option::Option inside Wire<T> directly.

Result

Error handling with a custom error enum.

#[ffi]
pub enum Error { Fail }

#[ffi]
pub fn pattern_result(x: ffi::Result<u32, Error>) -> ffi::Result<u32, Error> { x }

Strings

We have an owned UTF-8 string type that can be faster than marshalling in certain scenarios.

#[ffi]
pub fn utf8_string(x: ffi::String) -> ffi::String { x }

Note, this refers to the ffi::String type. We also support std::string::String inside Wire<T> directly.

Vectors

Owned, growable arrays.

#[ffi]
pub fn pattern_vec() -> ffi::Vec<u32> {
    vec![1, 2, 3].into()
}

Note, this refers to the ffi::Vec type. We also support std::vec::Vec inside Wire<T> directly.

Callbacks

Define named typed function-pointer callbacks (e.g., delegates in C#) with the callback! macro.

callback!(MyCallback(value: u32) -> u32);
callback!(SumDelegate(x: i32, y: i32) -> i32);
callback!(StringCallback(s: ffi::String));

#[ffi]
pub fn pattern_callback(callback: MyCallback, x: u32) -> u32 {
    callback.call(x)
}