flutter_rust_bridge v2: Flutter/Dart <-> Rust binding generator, feature-rich, but seamless and simple.
What's new in V2
Tap to expand
- From 1.x to 2.0.0-dev.0:
- Rapid setup: Only a one-liner command to integrate into your project.
- Arbitrary types: Use arbitrary Rust and Dart types without manual intervention, even if they are not serializable or non-clone (previously need some manual intervention).
- Async Rust: Support asynchronous Rust (
async fn
), in addition to sync Rust / async Dart / sync Dart. - Rust call Dart: Allow Rust to call Dart functions (previously only allow Dart to call Rust).
- Support whole folders as inputs: Previously only support one single file (e.g.
api.rs
). - Use libraries/tools in Flutter/Rust: All existing libraries, Flutter debuggers, ... Nothing to stop you from using them.
- From 2.0.0-dev.0 to 2.0.0:
- Parsing third-party packages: Scan and use existing Rust packages in Dart (experimental).
- Lifetimes: Support returning types with lifetime specifiers (experimental).
- Traits: Support traits as base classes and trait objects.
- New codec: A new codec,
SSE
, which is several times faster under some workloads. - Others (>200 PRs): Auto and manual accessors, object proxies, user-defined serializers, developer experience, deadlock-free auto locking, Rust initializers, included batteries, renaming and ignoring, improving streams, more types, ...
Please visit this page for more information and update guide.
🍀 What's this?
- Just write down normal Rust code (even with arbitrary types, closure,
&mut
, async, traits, etc) - And call it from Flutter, as if Rust code is normal Flutter code
- The bridge will generate all glues in between
📚 Quickstart
Create a working Flutter + Rust app and see it live, by running:
cargo install flutter_rust_bridge_codegen && flutter_rust_bridge_codegen create my_app && cd my_app && flutter run
Expand optional steps
(Optional) Edit rust/src/api/simple.rs
(e.g. Hello
-> Hi
), then see the change by:
flutter_rust_bridge_codegen generate && flutter run
For more elaborated quickstart, please visit this page.
🚀 Advantages
1. Officially Flutter Favorite
This package is officially Flutter Favorite, and is in the first batch of 7 packages at its rebooting. (another link)
2. Simplicity
(Tap to expand) Rapid setup, Write your code naturally, Use libraries/tools in Flutter/Rust, Battery included
- Rapid setup: Only a one-liner command to integrate into your project.
- Write your code naturally: Use your intuition and write the code you want. The bridge understands many advanced grammars (see below), allowing seamless calling Rust from Dart.
- Use libraries/tools in Flutter/Rust: All existing libraries, Flutter debuggers, ... Nothing to stop you from using them.
- Battery included: Even small things like logging and enable backtraces are configured in the starter kit.
3. Powerfulness
(Tap to expand) Arbitrary types, Async & sync, Two-way road, Auto-translatable types, Parsing third-party packages, Auto safety, Customizable & bare-metal mode, Cross-platform, ...
- Arbitrary types: Use arbitrary Rust and Dart types without manual intervention, even if they are not serializable or non-clone.
- Async & sync x Rust & Dart: Multi modes for various needs - Async Dart to avoid blocking the main thread, sync Dart for places needed (e.g. Widget.build); async Rust for IO bound tasks, thread pools for CPU-heavy computations.
- Two-way road: Not only can Dart call Rust - Rust can also call Dart.
- Auto-translatable types: Lots of types can be further translated to Dart native types, e.g. complex
enum
s andstruct
s, zero-copy big arrays, errors (Result
), andStream
s (iterator). - Parsing third-party packages: Scan and use existing Rust packages in Dart (experimental).
- Auto safety: Focus on your code, and forget memory safety, malloc/free, or undefined behavior completely.
- Customizable & bare-metal mode: Provide sensible defaults, but everything (loader, handler, ...) can be customized. You can even throw all away and only use the bare minimum calling.
- Cross-platform: Support Android, iOS, Windows, Linux, MacOS, and Web.
- Other features, e.g. support whole folders as input, pure-Dart compatible, instance and static methods, ...
4. Reliability
(Tap to expand) Solid CI, Used by many people, Easy to review, Fast, Hackable, Ask questions
- Solid CI: Valgrind & sanitizers (ASAN/MSAN/LSAN) for memory/UB-related bugs, testing per platform per mode, benchmarking, test coverage, post-release, etc, all guaranteed by CI.
- Used by many people: See here for an incomplete list.
- Easy to code-review & convince yourself: This package simply simulates how humans write boilerplate code. If you want to convince yourself (or your team) that it is safe, there is not much code to track.
- Fast: It is only a thin (though feature-rich) wrapper, benchmarked on CI, and even has multiple codecs for best performance under different workloads.
- Hackable: If (for whatever reason) you want to hack the source, there are contributor guides, code is modular, and the execution logic is intuitive.
- Ask questions: Feel free to ask questions in the issue tracker, and I usually reply within hours (if not sleeping).
Why Flutter + Rust?
Tap to expand
Firstly, super briefly introduce each component (you can find much more in a lot of blogs and posts):
- Flutter: Cross-platform, hot-reload, rapid-development, flexible UI toolkit.
- Rust: Highly efficient and performant, reliable, productive.
Typical scenarios to combine them include:
- UI framework for Rust: When you want a UI framework for your Rust system.
- Use arbitrary Rust libraries in Flutter: When the desired functionality only has a library in Rust, not Dart (Flutter).
- Need high-performance code for Flutter: Rust makes it easy and performant to write multi-thread code, algorithms, data-intensive operations, SIMD code, etc.
- ...
✨ Show me the code
Example 1
Simple Rust...
fn f(a: String, b: Vec<MyEnum>) -> MyStruct { ... }
...called from Dart, without manual intervention.
print(f(a: 'Hello', b: [MyEnum.c('Tom')]));
Example 2
Suppose we implement a word dictionary in Rust:
// ↱ Arbitrarily fancy Rust types
pub struct WordDict { .. }
// ↱ Support functions & methods
impl WordDict {
// ↱ Can call Dart back ↱ Translate errors
pub fn open(chooser: impl Fn(String) -> bool) -> Result<WordDict> { .. }
// ↱ Support async & sync Dart; property getter
#[frb(sync, getter)]
// ↱ Support T/&T/&mut T
pub fn size(&self) -> u32 { .. }
// ↱ Allow async & sync ↱ Support stream (iterator)
pub async fn search(&self, keyword: String, sink: StreamSink<String>) { .. }
}
Still seamlessly call in Dart:
final dict = await WordDict.open((situation) => true);
print(dict.size);
await for (final value in dict.search('something')) { print(value); }
There are still many features not covered here, such as parsing third party packages, lifetimes, traits, auto accessors, proxies, etc.
💡 Documentation
Check out the documentation for quickstart, full guides and more.
📎 P.S. Achieve ~60 FPS, no matter how janky the Flutter app was due to build/layout
Here is my another open-source library :) https://github.com/fzyzcjy/flutter_smooth.
✨ Acknowledgments and contributors
Firstly, I want to sincerely thank Dart, Flutter and Rust (alphabetical order). Dart provides a solid foundation for productive UI development, Flutter enables developers to make cross-platform apps with ease, and Rust empowers everyone to build reliable and efficient software. Without the languages and frameworks, this bridge connects absolutely nothing. Besides, I also want to express my thanks for conferring the official Flutter Favorite honor to the package. In addition, I also want to say thanks to the Dart, Flutter and Rust team members as well as community members, who have helped me during the development of flutter_rust_bridge by valuable discussions, insights, and actions.
Secondly, thanks goes to these wonderful contributors (emoji key following all-contributors specification):