Skip to content

Commit 7b777d0

Browse files
committed
Update README
1 parent c6cd1c5 commit 7b777d0

File tree

2 files changed

+130
-2
lines changed

2 files changed

+130
-2
lines changed

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919

2020
# The main branch is the v0.10, development version of `mlua`. Please see the [v0.9](https://github.com/mlua-rs/mlua/tree/v0.9) branch for the stable versions of `mlua`.
2121

22+
> **Note**
23+
>
24+
> See (upcoming) v0.10 [release notes](https://github.com/khvzak/mlua/blob/main/docs/release_notes/v0.10.md).
25+
2226
`mlua` is bindings to [Lua](https://www.lua.org) programming language for Rust with a goal to provide
2327
_safe_ (as far as it's possible), high level, easy to use, practical and flexible API.
2428

@@ -53,6 +57,7 @@ Below is a list of the available feature flags. By default `mlua` does not enabl
5357
* `send`: make `mlua::Lua: Send + Sync` (adds [`Send`] requirement to `mlua::Function` and `mlua::UserData`)
5458
* `serialize`: add serialization and deserialization support to `mlua` types using [serde] framework
5559
* `macros`: enable procedural macros (such as `chunk!`)
60+
* `anyhow`: enable `anyhow::Error` conversion into Lua
5661

5762
[5.4]: https://www.lua.org/manual/5.4/manual.html
5863
[5.3]: https://www.lua.org/manual/5.3/manual.html
@@ -128,7 +133,7 @@ Add to `Cargo.toml` :
128133

129134
``` toml
130135
[dependencies]
131-
mlua = { version = "0.9.9", features = ["lua54", "vendored"] }
136+
mlua = { version = "0.10.0-rc.1", features = ["lua54", "vendored"] }
132137
```
133138

134139
`main.rs`
@@ -163,7 +168,7 @@ Add to `Cargo.toml` :
163168
crate-type = ["cdylib"]
164169

165170
[dependencies]
166-
mlua = { version = "0.9.9", features = ["lua54", "module"] }
171+
mlua = { version = "0.10.0-rc.1", features = ["lua54", "module"] }
167172
```
168173

169174
`lib.rs` :

docs/release_notes/v0.10.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
## mlua v0.10 release notes
2+
3+
The v0.10 version of mlua has goal to improve the user experience while keeping the same performance and safety guarantees.
4+
This document highlights the most notable features. For a full list of changes, see the [CHANGELOG].
5+
6+
[CHANGELOG]: https://github.com/khvzak/mlua/blob/main/CHANGELOG.md
7+
8+
### New features
9+
10+
#### `'static` Lua types
11+
12+
In previous mlua versions, it was required to have a `'lua` lifetime attached to every Lua value. v0.9 introduced (experimental) owned types that are `'static` without a lifetime attached, but they kept strong references to the Lua instance.
13+
In v0.10 all Lua types are `'static` and have only weak reference to the Lua instance. It means they are more flexible and can be used in more places without worrying about memory leaks.
14+
15+
#### Truly `send` feature
16+
17+
In this version Lua is `Send + Sync` when the `send` feature flag is enabled (previously was only `Send`). It means Lua instance and their values can be safely shared between threads and used in multi threaded async contexts.
18+
19+
```rust
20+
let lua = Lua::new();
21+
22+
lua.globals().set("i", 0)?;
23+
let func = lua.load("i = i + ...").into_function()?;
24+
25+
std::thread::scope(|s| {
26+
s.spawn(|| {
27+
for i in 0..5 {
28+
func.call::<()>(i).unwrap();
29+
}
30+
});
31+
s.spawn(|| {
32+
for i in 0..5 {
33+
func.call::<()>(i).unwrap();
34+
}
35+
});
36+
});
37+
38+
assert_eq!(lua.globals().get::<i32>("i")?, 20);
39+
```
40+
41+
Under the hood, to synchronize access to the Lua state, mlua uses [`ReentrantMutex`] which can be recursively locked by a single thread. Only one thread can execute Lua code at a time, but it's possible to share Lua values between threads.
42+
43+
This has some performance penalties (about 10-20%) compared to the lock free mode. This flag is disabled by default and does not supported in module mode.
44+
45+
[`ReentrantMutex`]: https://docs.rs/parking_lot/latest/parking_lot/type.ReentrantMutex.html
46+
47+
#### Register Rust functions with variable number of arguments
48+
49+
The new traits `LuaNativeFn`/`LuaNativeFnMut`/`LuaNativeAsyncFn` have been introduced to provide a way to register Rust functions with variable number of arguments in Lua, without needing to pass all arguments as a tuple.
50+
51+
They are used by `Function::wrap`/`Function::wrap_mut`/`Function::wrap_async` methods:
52+
53+
```rust
54+
let add = Function::wrap(|a: i64, b: i64| Ok(a + b));
55+
56+
lua.globals().set("add", add).unwrap();
57+
58+
// Prints 50
59+
lua.load(r#"print(add(5, 45))"#).exec().unwrap();
60+
```
61+
62+
To wrap functions that return direct value (non-`Result`) you can use `Function::wrap_raw` method.
63+
64+
#### Setting metatable for Lua builtin types
65+
66+
For Lua builtin types (like `string`, `function`, `number`, etc.) that have a shared metatable for all instances, it's now possible to set a custom metatable for them.
67+
68+
```rust
69+
let mt = lua.create_table()?;
70+
mt.set("__tostring", lua.create_function(|_, b: bool| Ok(if b { "2" } else { "0" }))?)?;
71+
lua.set_type_metatable::<bool>(Some(mt));
72+
lua.load("assert(tostring(true) == '2')").exec().unwrap();
73+
```
74+
75+
### Improvements
76+
77+
#### New `ObjectLike` trait
78+
79+
The `ObjectLike` trait is a combination of the `AnyUserDataExt` and `TableExt` traits used in previous versions. It provides a unified interface for working with Lua tables and userdata.
80+
81+
#### `Either<L, R>` enum
82+
83+
The `Either<L, R>` enum is a simple enum that can hold either `L` or `R` value. It's useful when you need to return or receive one of two types in a function.
84+
This type implements `IntoLua` and `FromLua` traits and can generate a meaningful error message when conversion fails.
85+
86+
```rust
87+
let func = Function::wrap(|x: Either<i32, String>| Ok(format!("received: {x}")));
88+
89+
lua.globals().set("func", func).unwrap();
90+
91+
// Prints: received: 123
92+
lua.load(r#"print(func(123))"#).exec().unwrap();
93+
94+
// Prints: bad argument #1: error converting Lua table to Either<i32, String>
95+
lua.load(r#"print(pcall(func, {}))"#).exec().unwrap();
96+
```
97+
98+
#### `Lua::exec_raw` helper to execute low-level Lua C API code
99+
100+
For advanced users, it's now possible to execute low-level Lua C API code using the `Lua::exec_raw` method.
101+
102+
```rust
103+
let t = lua.create_sequence_from([1, 2, 3, 4, 5])?;
104+
let sum: i64 = unsafe {
105+
lua.exec_raw(&t, |state| {
106+
// top of the stack: table `t`
107+
let mut sum = 0;
108+
// push nil as the first key
109+
mlua::ffi::lua_pushnil(state);
110+
while mlua::ffi::lua_next(state, -2) != 0 {
111+
sum += mlua::ffi::lua_tointeger(state, -1);
112+
// Remove the value, keep the key for the next iteration
113+
mlua::ffi::lua_pop(state, 1);
114+
}
115+
mlua::ffi::lua_pop(state, 1);
116+
mlua::ffi::lua_pushinteger(state, sum);
117+
// top of the stack: sum
118+
})
119+
}?;
120+
assert_eq!(sum, 15);
121+
```
122+
123+
The `exec_raw` method is longjmp-safe. It's not recommended to move `Drop` types into the closure to avoid possible memory leaks.

0 commit comments

Comments
 (0)