7 个版本
0.5.0 | 2023年12月31日 |
---|---|
0.4.0 | 2022年8月20日 |
0.3.2 | 2022年8月14日 |
0.2.1 |
|
0.1.1-alpha.9 |
|
#54 in FFI
在 minutus-mrbgem-template 中使用
1.5MB
1K SLoC
Minutus
Minutus 是 mruby 的 Rust 绑定,它允许您无需编写繁琐的模板即可处理 mruby。深受 Magnus 的启发。
通过 minutus,您可以轻松地将 mruby 嵌入 Rust,并通过 Rust 创建 mrbgem。
Minutus 还提供了合理的 类型转换,您可以在 mruby 值上定义类型函数,并将 Rust 结构体封装在 mruby 对象中。
将 mruby 嵌入 Rust
您可以将 mruby 代码嵌入 Rust 代码中。
使用 link_mruby
功能将 minutus 添加到您的 crate 的依赖项中。
cargo add minutus --features link_mruby
编写代码如下
// src/main.rs
// This enables you to call `some_method` in mruby world.
minutus::define_funcall!{
fn some_method(self, arr: Vec<i64>) -> i64;
}
fn main() {
let runtime = minutus::Evaluator::build();
// Define `some_method` in mruby world
runtime.evaluate(
"
def some_method(arr)
p arr
arr.reduce(&:+)
end
"
).unwrap();
// Capture mruby's main object
let main = runtime.evaluate("self").unwrap();
// Call `some_method` on main object.
// Arguments and return values are automatically type-casted according to `define_funcall!` definition.
let retval: i64 = main.some_method(vec![1,2,3,4]).unwrap();
println!("retval is {}", retval);
}
然后,您可以运行您的代码
$ cargo run
[1, 2, 3, 4] // in mruby workd
retval is 10 // in rust world
如果您想使用自定义 build_config.rb
(例如,用于使用 mrbgems),您必须编写自定义 build.rs
Minutus 提供了相应的辅助工具。请参阅 示例/custom-mruby。
通过 Rust 创建 mrbgem
安装 minutus-mrbgem-template
并初始化 mrbgem。
$ cargo install minutus-mrbgem-template
$ minutus-mrbgem-template mruby-example
$ tree mruby-example
mruby-example
├── Cargo.lock
├── Cargo.toml
├── LICENSE
├── README.md
├── Rakefile
├── mrbgem.rake
├── mrblib
│ └── mrb_example.rb
├── mruby-example.gem
├── src
│ ├── dummy.c
│ └── lib.rs
└── test
└── mrb_example.rb
现在,您可以构建和测试 mrbgem。
$ cd mruby-example && rake test
...
Total: 1456
OK: 1449
KO: 0
Crash: 0
Warning: 0
Skip: 7
Time: 0.06 seconds
将 Rust 结构体封装在 mruby 对象中
您可以将 Rust 的结构体封装在 mruby 对象中。
以下示例在 mruby 中定义了 TestMrbgem
类,它具有类方法 new
和实例方法 distance
和 name_with_prefix
。
#[minutus::wrap(class_method = "new", method = "distance", method = "name_with_prefix")]
struct TestMrbgem {
x: i64,
y: i64,
name: String,
}
impl TestMrbgem {
#[minutus::class_method]
pub fn new(x: i64, y: i64, name: String) -> Self {
Self { x, y, name }
}
#[minutus::method]
pub fn distance(&self, other: &TestMrbgem) -> f64 {
(((self.x - other.x).pow(2) + (self.y - other.y).pow(2)) as f64).sqrt()
}
#[minutus::method]
pub fn name_with_prefix(&self, prefix: String) -> String {
[prefix, self.name.clone()].join("_")
}
}
在 mruby 值上定义类型函数
使用 define_funcall!
宏。
minutus::define_funcall! {
fn inspect(self) -> String;
fn concat(self, other: Vec<&str>) -> Vec<String> => "+";
}
fn main() {
let runtime = minutus::Evaluator::build();
let mruby_array = runtime.evaluate("['aaa', 'bbb']").unwrap();
assert_eq!("[\"aaa\", \"bbb\"]", mruby_array.inspect().unwrap());
assert_eq!(vec![String::from("aaa"), String::from("bbb"), String::from("ccc")], mruby_array.concat(vec!["ccc"]).unwrap());
}
类型转换
有关详细信息,请参阅 minutus/src/types。
Rust 类型 | mruby 类型 |
---|---|
i8 、i16 、i32 、i64 、isize |
整数 |
u8 、u16 、u32 、u64 、usize |
整数 |
f32 、f64 |
浮点数 |
字符串 |
字符串 |
可选<T> |
T 或 nil |
(T, U) 、(T, U, V) 等 |
[T, U] 、[T, U, V] 等 |
Vec<T> |
数组 |
std::collections::HashMap<T, U> |
Hash |
minutus::types::RSymbol |
Symbol |
bool |
任意对象 |
MrbData (由 minutus::wrap 标记的结构体) |
对应类 |
在 mruby 中,任何值都可以转换为 Rust 的 bool
。Rust 的 bool
转换为 mruby 的 true
或 false
。
支持的 mruby 版本
3.1.0 和 3.2.0 支持。您还可以使用 mruby 的 master
分支,但未进行测试。
[dependencies]
// Use 3.1.0
minutus = { features = ["mruby_3_1_0"] }
// Use master branch
minutus = { features = ["mruby_master"] }
命名
Minutus 是 Magnus 的反义词,意思是 小的。
依赖
~6–22MB
~358K SLoC