2 个版本

0.1.2 2020年7月1日
0.1.0 2020年6月30日

#451 in 过程宏

MIT/Apache

70KB
2K SLoC

Rust 1.5K SLoC // 0.0% comments Dart 357 SLoC

DUSTR

使用 dustr,您可以从 Dart 调用此 Rust 代码

#[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 是一个二进制文件,它解析 Rust 代码以生成其 Dart 绑定。Rust 代码必须使用来自 ffishim_derive 的过程宏从 ffishim 库进行标记。

这些过程宏生成一个与原始数据结构/函数兼容的 FFI API。这是必要的,因为许多基本的 Rust 类型(StringOptionVec 等)不遵循 C ABI。

安装与使用

现在,假设我们想重现我们的第一个例子。我们需要 make、cargo 和 Dart SDK。我们使用 cargo 安装 dustr

export PATH=$PATH:$HOME/.cargo/bin
cargo install dustr

我们还创建了自己的 hello crate,并将其标记为 C 动态库(cdylib,在 rusthello/target/debug 目录中生成 .so 共享对象)

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

我们趁机添加了代码(这次增加了更多的管道),并构建了库。现在让我们进入 Dart 部分...

dustr --dest darthello --name hello rusthello/
cd darthello; pub get; cd -

dustr 命令将创建一个包含对 rusthello 库绑定的 Dart 包。使用 pub get 拉取任何依赖项。我们现在将设置 Dart 应用程序,它将使用我们的绑定

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 -

现在我们可以运行应用程序。不要忘记提供 Rust 库

LD_LIBRARY_PATH=rusthello/target/debug dart dartapp/bin/main.dart

示例

您可以通过查看 tests 文件夹来找到 dustr 的行为示例。测试的结构如下

  • src/lib.rs:要公开的 Rust 库
  • Cargo.toml:Rust 库的清单(定义了 cdylib 等..)
  • pubspec.yaml:dart二进制文件的清单(定义了依赖生成的绑定)
  • bin/main.dart:使用此Rust库的dart代码
  • expected_output:包含运行C程序预期的输出

每个测试文件夹都是一个独立的应用程序。例如,你可以

  • 运行 make 来测试所有这些
  • target/bindings 层级中检查生成的绑定代码
  • 调整一个或两个测试来尝试行为并重新运行 make 来测试
  • 将它们用作模板来创建自己的Rust <-> dart集成

C ABI免责声明

由于dart ffi支持仍处于alpha阶段,它还不能完全消费C ABI。例如,它不支持嵌套结构,并且结构不能按值传递给函数。因此,我们使用的ffishim crate不会生成C-ABI代码,而是一个由dart ffi可消费的版本。

TODO/限制

此crate仍处于beta阶段。它还不适合用于生产。

错误

  • 修复不在struct/enum内时返回字符串的泄露
  • 修复不在struct/enum内时返回选项的泄露

特性

  • 适应ffishim中的潜在名称修饰(以避免重复)
  • 找到usize/isize/char的dart类型等效物
  • 实现DateTime行为

测试

  • 添加一个“完整”的测试/示例情况
  • 按领域重新组织测试(找到分类法)
  • 对一些用例进行基准测试

文档

  • 在README.md简介中写明此crate的功能
  • 在哪里写入doc.rs中的二进制文档?

依赖项

~5.5MB
~110K SLoC