uniffi-rs/examples
Ben Dean-Kawamura a4dae7e670 Added ffi-buffer scaffolding functions
These are alternate versions of the current scaffolding functions that
use u64 buffers to handle their input/output.

The main use case is the gecko-js bindings used in Firefox.  This allows
us to replace the generated C++ code with static code, since the
scaffolding functions now always have the exact same signature.

This commit generates FFI buffer versions for scaffolding functions
defined for user functions/methods.  It does not generate them for
functions with known/static signatures like the rust buffer FFI
functions, or the object clone/delete functions.  If the signature is
always the same, then there isn't a problem calling the normal
scaffolding functions.
2024-05-06 12:57:39 -04:00
..
app Use a workspace dependency for the top-level uniffi crate. (#1859) 2024-01-18 11:35:45 -05:00
arithmetic Added ffi-buffer scaffolding functions 2024-05-06 12:57:39 -04:00
arithmetic-procmacro Try removing build dependency in procmacro example 2024-02-06 14:11:25 -05:00
async-api-client Updating the async API client example 2024-03-23 11:34:55 -04:00
callbacks Use a workspace dependency for the top-level uniffi crate. (#1859) 2024-01-18 11:35:45 -05:00
custom-types Use a workspace dependency for the top-level uniffi crate. (#1859) 2024-01-18 11:35:45 -05:00
futures Use a workspace dependency for the top-level uniffi crate. (#1859) 2024-01-18 11:35:45 -05:00
fxa-client Update docs re uniffi.toml and tweaks to a couple of examples (#1783) 2023-10-09 13:45:12 -04:00
geometry Ruby: Enforce keyword arguments for constructors and implement default values in struct constructors 2024-03-07 16:23:27 +01:00
rondpoint Ruby: Enforce keyword arguments for constructors and implement default values in struct constructors 2024-03-07 16:23:27 +01:00
sprites Ruby: Enforce keyword arguments for constructors and implement default values in struct constructors 2024-03-07 16:23:27 +01:00
todolist Ruby: Enforce keyword arguments for constructors and implement default values in struct constructors 2024-03-07 16:23:27 +01:00
traits Use a workspace dependency for the top-level uniffi crate. (#1859) 2024-01-18 11:35:45 -05:00
README.md Foreign-implemented async trait methods (#2017) 2024-03-18 17:24:55 -04:00

README.md

Example uniffi components

This directory contains some small example components implemented using uniffi. It's currently being used more as a living test environment than user-facing docs, but hopefully it gives you a bit of an idea of what we're up to with this crate.

Newcomers are recommended to explore them in the following order:

  • ./arithmetic/ is the most minimal example - just some plain functions that operate on integers, and some minimal error handling.
  • ./arithmetic-procmacro/ is a copy of the above example implemented using procmacros - it has no UDL file nor build.rs script.
  • ./geometry/ shows how to use records and nullable types for working with more complex data.
  • ./sprites/ shows how to work with stateful objects that have methods, in classical object-oriented style.
  • ./todolist is a simplistic todo-list that can only add items and show the last item, meant to show how interacting with strings works.
  • ./rondpoint exercises complex data types by round-tripping them from the foreign-language code, through rust and back again.
  • ./fxa-client doesn't work yet, but it contains aspirational example of what the UDL might look like for an actual real-world component.
  • ./async-api-client shows how to handle async calls across the FFI. The foreign code supplies the HTTP client, the Rust code uses that client to expose a GitHub API client, then the foreign code consumes the client. All code on both sides of the FFI is async.

Each example has the following structure:

  • src/<namespace>.udl, the component interface definition which defines the main object and its methods. This is processed by functions in build.rs to generate Rust scaffolding for the component.
  • src/lib.rs, the core implementation of the component in Rust. This basically pulls in the generated Rust scaffolding via uniffi::include_scaffolding!() and fills in function implementations.
  • Cargo.toml configures the crate to build a cdylib with an appropriate name.
  • Some small test scripts that double as API examples in each target foreign language:
    • Kotlin tests/bindings/test_<namespace>.kts
    • Swift tests/bindings/test_<namespace>.swift
    • Python tests/bindings/test_<namespace>.py

If you want to try them out, you will need:

We publish a docker image that has all of this dependencies pre-installed, if you want to get up and running quickly.

With that in place, try the following:

  • Run cargo build. That compiles the component implementation into a native library named uniffi_<namespace> in ../target/debug/.
  • Run cargo test. This will run each of the foreign-language testcases against the compiled Rust code, confirming whether everything is working as intended.
  • Explore the build process in more detail:
    • Change to the root directory of this repo, so the uniffi-bindgen package referenced below can be found.
    • Run cargo run --bin uniffi-bindgen -- scaffolding examples/<example>/src/<namespace>.udl. This will generate the Rust scaffolding code which exposes a C FFI for the component. You can view the generatd code in ./src/<namespace>.uniffi.rs.
    • Run cargo run --bin uniffi-bindgen -- generate --language kotlin examples/<example>/src/<namespace>.udl. This will generate the foreign-language bindings for Kotlin, which load the compiled Rust code and use the C FFI generated above to interact with it. You can view the generated code in ./src/uniffi/<namespace>/<namespace>.kt.
    • Try using --language swift or --language python to explore the foreign-language bindings generated for other languages.