Crates.io | dustr |
lib.rs | dustr |
version | 0.1.2 |
source | src |
created_at | 2020-06-30 17:25:55.29105 |
updated_at | 2020-07-01 20:56:30.901111 |
description | Generate dart code based on a rust ffishim |
homepage | |
repository | https://github.com/mqnfred/dustr |
max_upload_size | |
id | 259911 |
size | 81,982 |
With dustr
, you can call this rust code:
#[ffishim_function]
fn hello(s: String) -> String {
format!("Hello, {}!", s)
}
from dart:
import 'package:hello/hello.dart';
void main() {
var greeting = hello("fred");
print("${greeting}");
}
dustr
is a binary that parses rust code to generate its dart bindings. The
rust code must be marked using the ffishim_derive procedural macros from
the ffishim library.
These procedural macros generate an FFI-compatible API around the original data
structure/function. This is necessary because many basic rust types (String
,
Option
, Vec
, ...) do not respect the C ABI.
Now, suppose we want to reproduce our first example. We need make, cargo and the dart sdk. We install dustr using cargo:
export PATH=$PATH:$HOME/.cargo/bin
cargo install dustr
We also create our hello crate which we will mark as C dynamic library (cdylib,
to generate a .so
shared object in the rusthello/target/debug
directory.)
cargo new --lib rusthello --name hello
cat >>rusthello/Cargo.toml <<EOF
ffishim = "^0"
ffishim_derive = "^0"
[lib]
crate-type = ["cdylib"]
EOF
cat >rusthello/src/lib.rs <<EOF
#[macro_use]
extern crate ffishim_derive;
#[ffishim_library]
#[ffishim_function]
fn hello(s: String) -> String {
format!("Hello, {}!", s)
}
EOF
cargo build --manifest-path=rusthello/Cargo.toml
ls rusthello/target/debug/libhello.so
We took the opportunity to add the code (with a healthy dose more plumbing this time) and build the library. Now let's step into the dart side...
dustr --dest darthello --name hello rusthello/
cd darthello; pub get; cd -
The dustr
command will create the dart package containing the bindings to the
rusthello library. pub get
pulls in any dependencies. We'll now set up the
dart app which will use our bindings:
mkdir -p dartapp/bin
cat >dartapp/bin/main.dart <<EOF
import 'package:hello/hello.dart';
void main() {
var greeting = hello("fred");
print("\${greeting}");
}
EOF
cat >dartapp/pubspec.yaml <<EOF
---
name: app
dependencies:
hello:
path: ../darthello
environment:
sdk: ">=2.0.0 <3.0.0"
EOF
cd dartapp; pub get; cd -
Now we can run the app. Don't forget to provide the rust library:
LD_LIBRARY_PATH=rusthello/target/debug dart dartapp/bin/main.dart
You can find examples of dustr
's behavior by looking at the tests
folder. The structure of the tests are as follow:
src/lib.rs
: the rust library to exposeCargo.toml
: manifest of the rust library (defines cdylib, etc..)pubspec.yaml
: manifest of dart binary (defines dep on generated bindings)bin/main.dart
: the dart code that uses this rust libraryexpected_output
: contains the output expected from running the C programEvery test folder is a stand-alone app. For example, you could:
make
to test all of themtarget/bindings
hierarchymake
to test things outBecause dart ffi support is still in alpha, it cannot quite consume the C ABI just yet. For example, it does not support nested structs, and structures cannot be passed by value to functions. For this reason, the ffishim crate we use does not generate C-ABI code exactly, but a bastard version consumable by the dart ffi.
This crate is still in beta. It is not fit for production use yet.