Expand description
Overview
Membrane works by inspecting public functions and their types at
compile time, then generating corresponding Dart code and C bindings capable of
calling those functions and representing their data. To mark a Rust function as accessible to Dart we
just apply the #[async_dart]
macro, Membrane handles everything else.
Functions published to Dart use Rust types for their parameters including scalar types, structs, or enums - no need to work with C types in your Rust code. Both async functions and streams are supported, return values are handled via a zero-copy buffer using the bincode encoding (bincode is very efficient because it encodes data only as opposed to structure + data). Membrane is being used by a large project with stringent performance requirements and with this zero-copy encoding approach we were able to achieve zero frame drops in Flutter while transferring significant amounts of data from Rust.
Usage
Since Membrane needs to compile the project and then run code to inspect types we need
a “post build” task to run Membrane, separate from your cargo build
step. This can
be accomplished by adding a generator.rs
(or similar) bin file to your project.
Example:
// lib.rs
#[async_dart(namespace = "accounts")]
pub async fn update_user(id: i64, user: User) -> Result<User, String> {
todo!()
}
#[async_dart(namespace = "accounts")]
pub fn users() -> impl Stream<Item = Result<User, MyError>> {
futures::stream::iter(vec![Ok(User::default())])
}
// bin.rs
fn main() {
let mut project = membrane::Membrane::new();
project
.package_destination_dir("../dart_example")
.package_name("example")
.using_lib("libexample")
.create_pub_package()
.write_api()
.write_c_headers()
.write_bindings();
}
For a runnable example see the example
directory
and run cargo run
to inspect the Dart output in the dart_example
directory.
By default Membrane stores metadata during the compile step whenever the project is compiled in debug mode. This has two implications:
cargo run --bin generator --release
won’t work.- A library compiled in
release
mode will have no Membrane metadata in the resulting binary.
If you need to force a different behavior the feature flags skip-generate
and generate
are
available to override the default behavior.