apt-get install libclang-dev
brew install llvm
On Linux ffigen looks for libclang at /usr/lib/llvm-11/lib/libclang.so
so you may need to symlink to the version specific library: ln -s /usr/lib/llvm-11/lib/libclang.so.1 /usr/lib/llvm-11/lib/libclang.so
.
View the example directory for a runnable example.
In your crate's lib.rs
add a RUNTIME
static that will survive for the lifetime of the program. RUNTIME
must hold an instance of membrane::App<Runtime>
where Runtime
has the membrane::Interface
trait implemented for whichever async framework you wish to use. In our examples we use tokio
to provide the runtime behavior, you are welcome to copy it:
``` rust
use membrane::runtime::{App, Interface, AbortHandle};
pub struct Runtime(tokio::runtime::Runtime);
impl Interface for Runtime {
fn spawn
fn spawnblocking
static RUNTIME: App
Then write some code that is annotated with the #[async_dart]
macro. No need to use C types here, just use Rust String
, i64
, f64
, bool
, structs, or enums as usual (or with Option
). The functions can be anywhere in your program and may return either an async Result<T, E>
or an impl Stream<Item = Result<T, E>>
:
``` rust use membrane::asyncdart; use tokiostream::Stream;
use crate::data;
pub fn contacts() -> impl Stream
pub async fn contact(id: String) -> Result
And now you are ready to generate the Dart package. Note that this code goes in a bin/generator.rs
or similar to be ran with cargo run
or a build task rather than in build.rs
(which only runs before compilation):
``` rust fn main() { // if nothing else in this generator.rs references lib.rs then // at least call a dummy function so lib.rs doesn't get optimized away example::load();
let mut project = membrane::Membrane::new(); project // name the output pub directory .packagedestinationdir("../dartexample") // the pub package name, if different than the directory .packagename("example") // give the basename of the .so or .dylib that your Rust program provides .usinglib("libexample") // use Dart enums instead of class enums .withcstyleenums(true) .createpubpackage() .writeapi() .writecheaders() .writebindings(); } ```
If everything went as planned you can now call Rust from Dart with:
bash
cd example
cargo run
cargo build
cd ../dart_example
cp ../example/target/debug/libexample.dylib .
dart --enable-asserts run
(--enable-asserts
enables a pretty print toString()
in the generated classes)
``` dart import 'package:dart_example/accounts.dart';
void main(List
If you get an error on Linux about not being able to load libexample.so
then add the pub package's path to LD_LIBRARY_PATH
.