2 个版本

使用旧的 Rust 2015

0.1.1 2017 年 4 月 21 日
0.1.0 2017 年 4 月 21 日

#2027Rust 模式

MIT 许可证

42KB
950

rust-lua53-ext

Rust 和 Lua 之间的抽象层

这是对 jcmoyer 的 rust-lua53 Lua 绑定的扩展。它使得 Rust 和 Lua 之间的交互变得更加简单和 Rust 风格。

尽管这是一个抽象层,但你仍然需要了解 Lua 的状态系统以及如何使用 rust-lua53。

为什么使用这个?

在处理 Lua 状态时,你需要记住有关 Lua 栈的一些信息,例如给定位置上值的类型,你正在处理的所有值在栈上的位置,栈的大小等。

lua53-ext 为你做了所有这些事情。你不需要直接与栈交互,而是通过一系列上下文来操作。当你使用上下文将变量推入栈时,所有推入的值将在上下文超出作用域时被弹出。

上下文

Context 实际上只是 Lua 状态的包装。你可以使用 Context::new 函数或 Context::push_context 函数在任何有 Lua 状态或另一个上下文的地方创建 Context。

变量

当你使用上下文将值推入 lua 栈时,你会得到一个表示推入值索引的值作为返回。例如,你可以通过 Context::push_integer 将整数推入栈。它接受一个参数,一个整数,并返回一个 LuaInteger,它表示新推入整数的索引(以及一些有用的抽象)。

示例

use context::Context;
use lua::{State, Type};
use types::LuaFunction;

fn main() {
    // Create a new rust-lua53 state
    let mut state = State::new();
    // Create a new Lua Context (Where the magic happens)
    let mut context = Context::new(&mut state);
    // Run a bit of code that creates a variable 'foo' with a value of 12.
    context.do_string("foo = 12").unwrap();
    // Push the global value 'foo' onto the stack as a LuaGeneric
    let lua_foo = context.push_global("foo");
    // Convert the LuaGeneric into an integer
    let result = lua_foo.get_value::<i64>(&mut context).unwrap();
    // Check result (12 = 12)
    assert_eq!(result, 12);
}

注意事项

Lua 类型与创建它们的上下文无关。以下都是有效的

fn main {
    let mut state = State::new();
    let mut context = Context::new(&mut state);
    let value;
    {
        // create a new context that sits on top of the old context
        let mut new_context = context.push_context();
        // value is now referencing a value on the stack
        value = new_context.push_integer(5);
        // the new context goes out of scope and 'value' is popped from the stack
    }
    context.push_integer(16);
    // Yet, I can still use 'value' here!
    context.set_global("foo", &value);
    // Crashes here (16 != 5)
    assert_eq!(Some(5), context.get_global("foo"));
}
fn main {
    // create a context 'foo'
    let mut state_foo = State::new();
    let mut context_foo = Context::new(&mut state_foo);

    // create a context 'bar'
    let mut state_bar = State::new();
    let mut context_bar = Context::new(&mut state_bar);
    
    // create some values for 'foo' and 'bar' (both have index 1)
    let value_foo = context_foo.push_integer(1);
    let value_bar = context_bar.push_integer(2);
    
    // woops! value_bar is defined for context_bar, not context_foo!
    context_foo.set_global("baz", &value_bar);
    
    // Crash here (1 != 2)
    assert_eq!(Some(2), context_foo.get_global("baz"));
}

依赖

~1MB
~21K SLoC