Change changelog, readme, examples, Cargo.toml for 0.12 release

This commit is contained in:
kyren 2018-02-10 19:04:18 -05:00
parent 1b92d3319c
commit 61236e685f
4 changed files with 90 additions and 22 deletions

View File

@ -1,3 +1,34 @@
## [0.12.0]
- Changed how userdata values are garbage collected, both to fix potential
panics and to simplify it. Now, when userdata is garbage collected, it will
be given a special "destructed userdata" metatable, and all interactions with
it will error with `CallbackDestructed`. From the rust side, an expired
userdata `AnyUserData` will not appear to be any rust type.
- Changed the `RegistryKey` API to be more useful and general. Now, it is not
100% necessary to manually drop `RegistryKey` instances in order to clean up
the registry, instead you can periodically call `Lua::expire_registry_values`
to remove registry values with `RegistryKey`s that have all been dropped.
Also, it is no longer a panic to use a `RegistryKey` from a mismatched Lua
instance, it is simply an error.
- Lua is now `Send`, and all userdata / callback functions have a Send
requirement. This is a potentially annoying breaking change, but there is a
new way to pass !Send types to Lua in a limited way.
- HUGE change, there is now a `Lua::scope` method, which allows passing
non-'static functions to Lua in a controlled way. It also allows passing
!Send functions and !Send userdata to Lua, with the same limitations. In
order to make this safe, the scope method behaves similarly to the `crossbeam`
crate's `crossbeam::scope` method, which ensures that types created within the
scope are destructed at the end of the scope. When using callbacks / userdata
created within the scope, the callbakcs / userdata are guaranteed to be
destructed at the end of the scope, and inside Lua references to them are in
an invalidated "destructed" state. This destructed state was already possible
to observe through `__gc` methods, so it doesn't introduce anything new, but
it has been fixed so that it cannot cause panics, and has a specific error
type.
- Correctly error on passing too many arguments to an `rlua::Function`, and
correctly error when returning too many results from a callback. Previously,
this was a panic.
## [0.11.0]
- `rlua::Error` now implements `failure::Fail` and not `std::error::Error`, and
external errors now require `failure::Fail`. This is the only API

View File

@ -1,6 +1,6 @@
[package]
name = "rlua"
version = "0.11.0"
version = "0.12.0"
authors = ["kyren <catherine@chucklefish.org>"]
description = "High level bindings to Lua 5.3"
repository = "https://github.com/chucklefish/rlua"

View File

@ -1,10 +1,10 @@
# rlua -- High level bindings between Rust and Lua
[![Build Status](https://travis-ci.org/chucklefish/rlua.svg?branch=master)](https://travis-ci.org/chucklefish/rlua)
[![Latest Version](https://img.shields.io/crates/v/rlua.svg)](https://crates.io/crates/rlua)
[![API Documentation](https://docs.rs/rlua/badge.svg)](https://docs.rs/rlua)
[API Documentation](https://docs.rs/rlua)
[Examples](examples/examples.rs)
[Guided Tour](examples/guided_tour.rs)
This library is a high level interface between Rust and Lua. Its major goal is
to expose as easy to use, practical, and flexible of an API between Rust and Lua

View File

@ -1,20 +1,20 @@
extern crate rlua;
use std::f32;
use std::iter::FromIterator;
use rlua::{Function, Lua, MetaMethod, Result, UserData, UserDataMethods, Variadic};
fn examples() -> Result<()> {
// Create a Lua context with Lua::new(). Eventually, this will allow
// further control on the lua std library, and will specifically allow
// limiting Lua to a subset of "safe" functionality.
fn guided_tour() -> Result<()> {
// Create a Lua context with `Lua::new()`. Eventually, this will allow further control on the
// lua std library, and will specifically allow limiting Lua to a subset of "safe"
// functionality.
let lua = Lua::new();
// You can get and set global variables. Notice that the globals table here
// is a permanent reference to _G, and it is mutated behind the scenes as
// lua code is loaded. This API is based heavily around internal mutation
// (just like lua itself).
// You can get and set global variables. Notice that the globals table here is a permanent
// reference to _G, and it is mutated behind the scenes as lua code is loaded. This API is
// based heavily around internal mutation (just like lua itself).
let globals = lua.globals();
@ -24,8 +24,8 @@ fn examples() -> Result<()> {
assert_eq!(globals.get::<_, String>("string_var")?, "hello");
assert_eq!(globals.get::<_, i64>("int_var")?, 42);
// You can load and evaluate lua code. The second parameter here gives the
// chunk a better name when lua error messages are printed.
// You can load and evaluate lua code. The second parameter here gives the chunk a better name
// when lua error messages are printed.
lua.exec::<()>(
r#"
@ -54,7 +54,7 @@ fn examples() -> Result<()> {
let v: i64 = map_table.get("two")?;
assert_eq!(v, 2);
// You can pass values like Table back into Lua
// You can pass values like `Table` back into Lua
globals.set("array_table", array_table)?;
globals.set("map_table", map_table)?;
@ -77,18 +77,25 @@ fn examples() -> Result<()> {
let print: Function = globals.get("print")?;
print.call::<_, ()>("hello from rust")?;
// This API handles variadics using tuples. This is one way to call a function with multiple
// parameters:
// This API generally handles variadics using tuples. This is one way to call a function with
// multiple parameters:
print.call::<_, ()>(("hello", "again", "from", "rust"))?;
// You can bind rust functions to lua as well. Callbacks receive the lua state itself as their
// But, you can also pass variadic arguments with the `Variadic` type.
print.call::<_, ()>(Variadic::from_iter(
["hello", "yet", "again", "from", "rust"].iter().cloned(),
))?;
// You can bind rust functions to lua as well. Callbacks receive the Lua state itself as their
// first parameter, and the arguments given to the function as the second parameter. The type
// of the arguments can be anything that is convertible from the set of parameters, in this
// case, the function expects two string sequences.
// of the arguments can be anything that is convertible from the parameters given by Lua, in
// this case, the function expects two string sequences.
let check_equal = lua.create_function(|_, (list1, list2): (Vec<String>, Vec<String>)| {
// This function just checks whether two string lists are equal, and in an inefficient way.
// Lua callbacks return rlua::Result, an Ok value is a normal return, and an Err return
// Lua callbacks return `rlua::Result`, an Ok value is a normal return, and an Err return
// turns into a Lua 'error'. Again, any type that is convertible to lua may be returned.
Ok(list1 == list2)
})?;
@ -137,9 +144,39 @@ fn examples() -> Result<()> {
assert!(lua.eval::<f32>("(vec2(1, 2) + vec2(2, 2)):magnitude()", None)? - 5.0 < f32::EPSILON);
// Normally, Rust types passed to `Lua` must be `Send`, because `Lua` itself is `Send`, and must
// be `'static`, because there is no way to tell when Lua might garbage collect them. There is,
// however, a limited way to lift both of these restrictions. You can call `Lua::scope` to
// create userdata types that do not have to be `Send`, and callback types that do not have to
// be `Send` OR `'static`.
let mut rust_val = 0;
lua.scope(|scope| {
// We create a 'sketchy' lua callback that modifies the variable `rust_val`. Outside of a
// `Lua::scope` call, this would not be allowed.
lua.globals().set(
"sketchy",
scope.create_function_mut(|_, ()| {
rust_val = 42;
Ok(())
})?,
)?;
lua.eval::<()>("sketchy()", None)
})?;
// We were able to run our 'sketchy' function inside the scope just fine. However, if we try to
// run our 'sketchy' function outside of the scope, the function we created will have been
// destroyed and we will generate an error.
assert_eq!(rust_val, 42);
assert!(lua.eval::<()>("sketchy()", None).is_err());
Ok(())
}
fn main() {
examples().unwrap();
guided_tour().unwrap();
}