Name Description Size
callbackinterface.rs Callback interfaces are traits specified in UDL which can be implemented by foreign languages. # Using callback interfaces 1. Define a Rust trait. This toy example defines a way of Rust accessing a key-value store exposed by the host operating system (e.g. the key chain). ``` trait Keychain: Send { fn get(&self, key: String) -> Option<String>; fn put(&self, key: String, value: String); } ``` 2. Define a callback interface in the UDL ```idl callback interface Keychain { string? get(string key); void put(string key, string data); }; ``` 3. And allow it to be passed into Rust. Here, we define a constructor to pass the keychain to rust, and then another method which may use it. In UDL: ```idl object Authenticator { constructor(Keychain keychain); void login(); } ``` In Rust: ``` # trait Keychain: Send { # fn get(&self, key: String) -> Option<String>; # fn put(&self, key: String, value: String); # } struct Authenticator { keychain: Box<dyn Keychain>, } impl Authenticator { pub fn new(keychain: Box<dyn Keychain>) -> Self { Self { keychain } } pub fn login(&self) { let username = self.keychain.get("username".into()); let password = self.keychain.get("password".into()); } } ``` 4. Create an foreign language implementation of the callback interface. In this example, here's a Kotlin implementation. ```kotlin class AndroidKeychain: Keychain { override fun get(key: String): String? { // … elide the implementation. return value } override fun put(key: String) { // … elide the implementation. } } ``` 5. Pass the implementation to Rust. Again, in Kotlin ```kotlin val authenticator = Authenticator(AndroidKeychain()) authenticator.login() ``` # How it works. ## High level Uniffi generates a protocol or interface in client code in the foreign language must implement. For each callback interface, UniFFI defines a VTable. This is a `repr(C)` struct where each field is a `repr(C)` callback function pointer. There is one field for each method, plus an extra field for the `uniffi_free` method. The foreign code registers one VTable per callback interface with Rust. VTable methods have a similar signature to Rust scaffolding functions. The one difference is that values are returned via an out pointer to work around a Python bug (https://bugs.python.org/issue5710). The foreign object that implements the interface is represented by an opaque handle. UniFFI generates a struct that implements the trait by calling VTable methods, passing the handle as the first parameter. When the struct is dropped, the `uniffi_free` method is called. 6812
ffidefault.rs FfiDefault trait When we make a FFI call into Rust we always need to return a value, even if that value will be ignored because we're flagging an exception. This trait defines what that value is for our supported FFI types. 1798
ffiserialize.rs 13077
foreignbytes.rs 3988
foreigncallbacks.rs This module contains code to handle foreign callbacks - C-ABI functions that are defined by a foreign language, then registered with UniFFI. These callbacks are used to implement callback interfaces, async scheduling etc. Foreign callbacks are registered at startup, when the foreign code loads the exported library. For each callback type, we also define a "cell" type for storing the callback. 1393
foreignfuture.rs This module defines a Rust Future that wraps an async foreign function call. The general idea is to create a oneshot channel, hand the sender to the foreign side, and await the receiver side on the Rust side. The foreign side should: * Input a [ForeignFutureCallback] and a `u64` handle in their scaffolding function. This is the sender, converted to a raw pointer, and an extern "C" function that sends the result. * Return a [ForeignFuture], which represents the foreign task object corresponding to the async function. * Call the [ForeignFutureCallback] when the async function completes with: * The `u64` handle initially passed in * The `ForeignFutureResult` for the call * Wait for the [ForeignFutureHandle::free] function to be called to free the task object. If this is called before the task completes, then the task will be cancelled. 8325
handle.rs 1569
mod.rs Types that can cross the FFI boundary. 825
rustbuffer.rs 13685
rustcalls.rs # Low-level support for calling rust functions This module helps the scaffolding code make calls to rust functions and pass back the result to the FFI bindings code. It handles: - Catching panics - Adapting the result of `Return::lower_return()` into either a return value or an exception 11307
rustfuture