mirror of
https://github.com/mlua-rs/mlua
synced 2026-06-08 16:05:43 +00:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cdc1c8415e | |||
| f2142731fd | |||
| 1dd62c5ffc | |||
| 95d8b2fd0f | |||
| 51a2959312 | |||
| 28bcc73f2c | |||
| 8b71f94141 | |||
| 3bda1351c3 | |||
| 4daa631178 | |||
| 9f5325ef2f | |||
| 6fb65a8fbe | |||
| f6dff65d9b | |||
| 4fa9aa1e5b | |||
| e1c075fa51 | |||
| df9251fb52 | |||
| ead6be4a52 | |||
| 4f48c7e5dc | |||
| fac39a2f46 | |||
| 483e6be207 | |||
| 0e030d21b0 |
@@ -218,7 +218,7 @@ jobs:
|
||||
- run: cargo fmt -- --check
|
||||
|
||||
clippy:
|
||||
name: Clippy check
|
||||
name: Clippy
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -229,7 +229,7 @@ jobs:
|
||||
with:
|
||||
toolchain: nightly
|
||||
components: clippy
|
||||
- uses: actions-rs/clippy-check@v1
|
||||
- uses: giraffate/clippy-action@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot,unstable"
|
||||
reporter: 'github-pr-review'
|
||||
clippy_flags: --features "${{ matrix.lua }},vendored,async,send,serialize,macros,parking_lot,unstable"
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
## v0.9.0-rc.2
|
||||
|
||||
- Added `#[derive(FromLua)]` macro to opt-in into `FromLua<T> where T: 'static + Clone` (userdata type).
|
||||
- Support vendored module mode for windows (raw-dylib linking, Rust 1.71+)
|
||||
- `module` and `vendored` features are now mutually exclusive
|
||||
- Use `C-unwind` ABI (Rust 1.71+)
|
||||
- Changed `AsChunk` trait to support capturing wrapped Lua types
|
||||
|
||||
## v0.9.0-rc.1
|
||||
|
||||
- `UserDataMethods::add_async_method()` takes `&T` instead of cloning `T`
|
||||
|
||||
+4
-3
@@ -1,7 +1,8 @@
|
||||
[package]
|
||||
name = "mlua"
|
||||
version = "0.9.0-rc.1" # remember to update mlua_derive
|
||||
version = "0.9.0-rc.2" # remember to update mlua_derive
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>", "kyren <catherine@chucklefish.org>"]
|
||||
rust-version = "1.71"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/khvzak/mlua"
|
||||
documentation = "https://docs.rs/mlua"
|
||||
@@ -43,7 +44,7 @@ macros = ["mlua_derive/macros"]
|
||||
unstable = []
|
||||
|
||||
[dependencies]
|
||||
mlua_derive = { version = "=0.9.0-rc.1", optional = true, path = "mlua_derive" }
|
||||
mlua_derive = { version = "=0.9.0-rc.2", optional = true, path = "mlua_derive" }
|
||||
bstr = { version = "1.0", features = ["std"], default_features = false }
|
||||
once_cell = { version = "1.0" }
|
||||
num-traits = { version = "0.2.14" }
|
||||
@@ -54,7 +55,7 @@ erased-serde = { version = "0.3", optional = true }
|
||||
serde-value = { version = "0.7", optional = true }
|
||||
parking_lot = { version = "0.12", optional = true }
|
||||
|
||||
ffi = { package = "mlua-sys", version = "0.2.1", path = "mlua-sys" }
|
||||
ffi = { package = "mlua-sys", version = "0.3.0", path = "mlua-sys" }
|
||||
|
||||
[dev-dependencies]
|
||||
rustyline = "12.0"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
[docs.rs]: https://docs.rs/mlua
|
||||
[Coverage Status]: https://codecov.io/gh/khvzak/mlua/branch/master/graph/badge.svg?token=99339FS1CG
|
||||
[codecov.io]: https://codecov.io/gh/khvzak/mlua
|
||||
[MSRV]: https://img.shields.io/badge/rust-1.63+-brightgreen.svg?&logo=rust
|
||||
[MSRV]: https://img.shields.io/badge/rust-1.71+-brightgreen.svg?&logo=rust
|
||||
|
||||
[Guided Tour] | [Benchmarks] | [FAQ]
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
> **Note**
|
||||
>
|
||||
> Please see the [v0.8](https://github.com/khvzak/mlua/tree/v0.8) branch for the stable versions of `mlua` released to crates.io.
|
||||
>
|
||||
> v0.9 release notes can be found [here](docs/release_notes/v0.9.md).
|
||||
|
||||
`mlua` is bindings to [Lua](https://www.lua.org) programming language for Rust with a goal to provide
|
||||
_safe_ (as far as it's possible), high level, easy to use, practical and flexible API.
|
||||
@@ -98,12 +100,12 @@ You have to enable one of the features: `lua54`, `lua53`, `lua52`, `lua51`, `lua
|
||||
|
||||
By default `mlua` uses `pkg-config` tool to find lua includes and libraries for the chosen Lua version.
|
||||
In most cases it works as desired, although sometimes could be more preferable to use a custom lua library.
|
||||
To achieve this, mlua supports `LUA_INC`, `LUA_LIB`, `LUA_LIB_NAME` and `LUA_LINK` environment variables.
|
||||
To achieve this, mlua supports `LUA_LIB`, `LUA_LIB_NAME` and `LUA_LINK` environment variables.
|
||||
`LUA_LINK` is optional and may be `dylib` (a dynamic library) or `static` (a static library, `.a` archive).
|
||||
|
||||
An example how to use them:
|
||||
``` sh
|
||||
my_project $ LUA_INC=$HOME/tmp/lua-5.2.4/src LUA_LIB=$HOME/tmp/lua-5.2.4/src LUA_LIB_NAME=lua LUA_LINK=static cargo build
|
||||
my_project $ LUA_LIB=$HOME/tmp/lua-5.2.4/src LUA_LIB_NAME=lua LUA_LINK=static cargo build
|
||||
```
|
||||
|
||||
`mlua` also supports vendored lua/luajit using the auxiliary crates [lua-src](https://crates.io/crates/lua-src) and
|
||||
@@ -117,7 +119,7 @@ Add to `Cargo.toml` :
|
||||
|
||||
``` toml
|
||||
[dependencies]
|
||||
mlua = { version = "0.8", features = ["lua54", "vendored"] }
|
||||
mlua = { version = "0.9.0-rc.2", features = ["lua54", "vendored"] }
|
||||
```
|
||||
|
||||
`main.rs`
|
||||
@@ -152,7 +154,7 @@ Add to `Cargo.toml` :
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
mlua = { version = "0.8", features = ["lua54", "vendored", "module"] }
|
||||
mlua = { version = "0.9.0-rc.2", features = ["lua54", "vendored", "module"] }
|
||||
```
|
||||
|
||||
`lib.rs` :
|
||||
@@ -197,13 +199,11 @@ rustflags = [
|
||||
]
|
||||
```
|
||||
On Linux you can build modules normally with `cargo build --release`.
|
||||
Vendored and non-vendored builds are supported for these OS.
|
||||
|
||||
On Windows `vendored` mode for modules is not supported since you need to link to a Lua dll.
|
||||
Easiest way is to use either MinGW64 (as part of [MSYS2](https://github.com/msys2/msys2) package) with `pkg-config` or
|
||||
MSVC with `LUA_INC` / `LUA_LIB` / `LUA_LIB_NAME` environment variables.
|
||||
On Windows the target module will be linked with `lua5x.dll` library (depending on your feature flags).
|
||||
Your main application should provide this library.
|
||||
|
||||
More details about compiling and linking Lua modules can be found on the [Building Modules](http://lua-users.org/wiki/BuildingModules) page.
|
||||
Module builds don't require Lua lib or headers to be installed on the system.
|
||||
|
||||
### Publishing to luarocks.org
|
||||
|
||||
|
||||
@@ -0,0 +1,364 @@
|
||||
## mlua v0.9 release notes
|
||||
|
||||
The v0.9 version of mlua is a major release that includes a number of API changes and improvements. This release is a stepping stone towards the v1.0.
|
||||
This document highlights the most important changes. For a full list of changes, see the [CHANGELOG].
|
||||
|
||||
[CHANGELOG]: https://github.com/khvzak/mlua/blob/master/CHANGELOG.md
|
||||
|
||||
### New features
|
||||
|
||||
#### 1. New Any UserData API
|
||||
|
||||
This is a long awaited feature that allows to register in Lua foreign types that cannot implement `UserData` trait because of the Rust orphan rules.
|
||||
|
||||
Now you can register any type that implements [`Any`] trait as a userdata type.
|
||||
|
||||
Consider the following example:
|
||||
|
||||
```rust
|
||||
lua.register_userdata_type::<std::string::String>(|reg| {
|
||||
reg.add_method("len", |_, this, ()| Ok(this.len()));
|
||||
|
||||
reg.add_method_mut("push", |_, this, s: String| {
|
||||
this.push_str(&s);
|
||||
Ok(())
|
||||
});
|
||||
|
||||
reg.add_meta_method(MetaMethod::ToString, |lua, this, ()| lua.create_string(this));
|
||||
})?;
|
||||
|
||||
let s = lua.create_any_userdata("hello".to_string())?;
|
||||
lua.load(chunk! {
|
||||
print("s:len() is " .. $s:len())
|
||||
$s:push(" world")
|
||||
// Prints: hello, world
|
||||
print($s)
|
||||
})
|
||||
.exec()?;
|
||||
```
|
||||
|
||||
In this example we registered [`std::string::String`] as a userdata type with a set of methods and then created an instance of this type in Lua.
|
||||
|
||||
It's _not_ required to register a type before using the `Lua::create_any_userdata()` method, instead an empty metatable will be created for you.
|
||||
You can also register the same type multiple times with different methods. Any previously created instances will share the old metatable, while new instances will have the new one.
|
||||
|
||||
The new set of API is called `any_userdata` because it allows to register types that implements [`Any`] trait.
|
||||
|
||||
[`std::string::String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html
|
||||
[`Any`]: https://doc.rust-lang.org/stable/std/any/trait.Any.html
|
||||
|
||||
#### 2. Scope support for the new any userdata types
|
||||
|
||||
When you need to create non-static userdata instances in Lua, the usual way is use `Lua::scope()` helper to make them scoped. When out of scope, any scoped objects will be automatically
|
||||
dropped. The only downside of this approach is that every new instance will have a new metatable. This is not very fast if you need to create a lot of instances.
|
||||
|
||||
With the new Any UserData API, you can place non-static references `&T` where `T: 'static` into a scope and they will share a single static metatable.
|
||||
|
||||
```rust
|
||||
lua.register_userdata_type::<std::string::String>(|reg| {
|
||||
reg.add_method_mut("replace", |_, this, (pat, to): (String, String)| {
|
||||
*this = this.replace(&pat, &to);
|
||||
Ok(())
|
||||
});
|
||||
|
||||
reg.add_meta_method(MetaMethod::ToString, |lua, this, ()| lua.create_string(this));
|
||||
})?;
|
||||
|
||||
let mut s = "hello, world".to_string();
|
||||
|
||||
lua.scope(|scope| {
|
||||
// This userdata instance holds only a mutable reference to our string
|
||||
let ud = scope.create_any_userdata_ref_mut(&mut s)?;
|
||||
lua.load(chunk! {
|
||||
$ud:replace("world", "user")
|
||||
})
|
||||
.exec()
|
||||
})?;
|
||||
|
||||
// Prints: hello, user!
|
||||
println!("{s}!");
|
||||
```
|
||||
|
||||
#### 3. Owned types (`unstable`)
|
||||
|
||||
One of the common questions was how to embed a Lua type into Rust struct to use it later. It was non-trivial to do because of the `'lua` lifetime attached to every Lua value.
|
||||
|
||||
In v0.9 mlua introduces "owned" types `OwnedTable`/`OwnedFunction`/`OwnedString`/`OwnedAnyUserData` that are `'static` (no lifetime attached).
|
||||
|
||||
```rust
|
||||
let lua = Lua::new();
|
||||
|
||||
struct MyStruct {
|
||||
table: OwnedTable,
|
||||
func: OwnedFunction,
|
||||
}
|
||||
|
||||
let my_struct = MyStruct {
|
||||
table: lua.globals().into_owned(),
|
||||
func: lua
|
||||
.create_function(|_, t: Table| Ok(format!("{t:#?}")))?
|
||||
.into_owned(),
|
||||
};
|
||||
|
||||
// It's safe to drop Lua!
|
||||
drop(lua);
|
||||
|
||||
let result = my_struct.func.call::<_, String>(my_struct.table)?;
|
||||
println!("{result}");
|
||||
```
|
||||
|
||||
Prior to v0.9, it was possible to do by creating a reference to the Lua value in registry using `Lua::create_registry_value()`
|
||||
and retrieving value later using `Lua::registry_value()` method.
|
||||
|
||||
All owned handles hold a *strong* reference to the current Lua instance.
|
||||
Be warned, if you place them into a Lua type (eg. `UserData` or a Rust callback), it is *very easy*
|
||||
to accidentally cause reference cycles that would prevent destroying Lua instance.
|
||||
|
||||
Please note this functionality is available under the `unstable` feature flag and not available when the `send` feature is enabled.
|
||||
|
||||
#### New ffi module
|
||||
|
||||
In v0.9 release the internal `ffi` module has been moved into the new [`mlua-sys`] crate and became available for public use.
|
||||
This crate provides unified Lua FFI API (targeting Lua 5.4) using a (limited) compatibility layer for older versions.
|
||||
|
||||
mlua re-exports the `ffi` module aliasing the `mlua-sys` crate and provides (unsafe) functionality to work with raw Lua state:
|
||||
|
||||
```rust
|
||||
unsafe {
|
||||
unsafe extern "C-unwind" fn lua_add(state: *mut mlua::lua_State) -> i32 {
|
||||
let a = mlua::ffi::luaL_checkinteger(state, 1);
|
||||
let b = mlua::ffi::luaL_checkinteger(state, 2);
|
||||
mlua::ffi::lua_pushinteger(state, a + b);
|
||||
1
|
||||
}
|
||||
|
||||
let add = lua.create_c_function(lua_add)?;
|
||||
assert_eq!(add.call::<_, i32>((2, 3))?, 5);
|
||||
}
|
||||
```
|
||||
|
||||
[`mlua-sys`]: https://crates.io/crates/mlua-sys
|
||||
|
||||
#### Luau JIT support
|
||||
|
||||
mlua brings support for the new experimental [Luau] JIT backend under the `luau-jit` feature flag. This backend is still under development and not yet ready for production use.
|
||||
|
||||
To enable it, just call `lua.enable_jit(true)` before loading Lua code. mlua will automatically trigger JIT compilation for new Lua chunks.
|
||||
|
||||
When calling this function with `false` argument, mlua will disable JIT compilation but any previously compiled chunks will remain JIT-compiled.
|
||||
|
||||
[Luau]: https://luau-lang.org
|
||||
|
||||
### Improvements
|
||||
|
||||
#### 1. Better error reporting
|
||||
|
||||
When calling a Rust function from Lua and passing wrong arguments, previous mlua versions reported a error message without any context or reference to the particular argument.
|
||||
|
||||
In v0.9 it reports a error message with the argument index and expected type:
|
||||
|
||||
```rust
|
||||
let func = lua.create_function(|_, _a: i32| Ok(()))?;
|
||||
lua.load(chunk! {
|
||||
local ok, err = pcall($func, "not a number")
|
||||
// Prints: bad argument #1: error converting Lua string to i32 (expected number or string coercible to number)
|
||||
print(err)
|
||||
})
|
||||
.exec()?;
|
||||
```
|
||||
|
||||
Similar changes have been made for userdata functions and methods:
|
||||
|
||||
```rust
|
||||
lua.register_userdata_type::<&'static str>(|reg| {
|
||||
reg.add_method("len", |_, this, ()| Ok(this.len()));
|
||||
})?;
|
||||
|
||||
let s = lua.create_any_userdata("hello")?;
|
||||
lua.load(chunk! {
|
||||
local ok, err = pcall($s.len, 123)
|
||||
// Prints: bad argument `self` to `&str.len`: error converting Lua integer to userdata
|
||||
print(err)
|
||||
})
|
||||
.exec()?;
|
||||
```
|
||||
|
||||
#### 2. Error context
|
||||
|
||||
Similar to the [`anyhow`] Error type, now it's possible to attach context to Lua errors:
|
||||
|
||||
```rust
|
||||
let read = lua.create_function(|lua, path: String| {
|
||||
let bytes = std::fs::read(&path)
|
||||
.into_lua_err()
|
||||
.context(format!("Failed to open `{path}`"))?;
|
||||
Ok(lua.create_string(bytes))
|
||||
})?;
|
||||
|
||||
lua.load(chunk! {
|
||||
local ok, err = pcall($read, "/nonexistent")
|
||||
print(err)
|
||||
})
|
||||
.exec()?;
|
||||
|
||||
Prints:
|
||||
```text
|
||||
Failed to open /nonexistent
|
||||
No such file or directory (os error 2)
|
||||
stack traceback:
|
||||
...
|
||||
```
|
||||
|
||||
[`anyhow`]: https://crates.io/crates/anyhow
|
||||
|
||||
#### 4. New methods `Function::wrap`/`AnyUserData::wrap`
|
||||
|
||||
Sometimes it's useful to have `IntoLua` trait implementation for a Rust function or type `T: Any` without needing to call `Lua::create_function()`/`Lua::create_any_userdata()` methods.
|
||||
Since v0.9 you can call the new methods `Function::wrap()`/`AnyUserData::wrap()` that allows to do this. They return an abstract type that `impl IntoLua`:
|
||||
|
||||
```rust
|
||||
lua.globals().set("print_rust", Function::wrap(|_, s: String| Ok(println!("{}", s))))?;
|
||||
lua.globals().set("rust_ud", AnyUserData::wrap("hello"))?;
|
||||
```
|
||||
|
||||
In addition there are also `Function::wrap_mut()`/`Function::wrap_async()` methods that allow to wrap mutable and async functions respectively.
|
||||
|
||||
For a `T: 'UserData + 'static` the `IntoLua` trait is still always implemented.
|
||||
|
||||
#### `UserDataRef` and `UserDataRefMut` type wrappers
|
||||
|
||||
The new wrappers `UserDataRef` and `UserDataRefMut` are receivers for userdata type `T` and borrow underlying instance for the lifetime of the wrapper.
|
||||
|
||||
```rust
|
||||
lua.globals()
|
||||
.set("ud", AnyUserData::wrap("hello".to_string()))?;
|
||||
|
||||
let mut ud_mut: UserDataRefMut<String> = lua.globals().get("ud")?;
|
||||
ud_mut.push_str(", Rust");
|
||||
drop(ud_mut);
|
||||
|
||||
let ud_ref: UserDataRef<String> = lua.globals().get("ud")?;
|
||||
// Prints: hello, Rust
|
||||
println!("{}", *ud_ref);
|
||||
```
|
||||
|
||||
In the previous mlua versions the same functionality can be achieved by receiving `AnyUserData` and calling `AnyUserData::borrow()`/`AnyUserData::borrow_mut()` methods.
|
||||
|
||||
The new wrappers are identical to Rust [`Ref`]/[`RefMut`] types.
|
||||
|
||||
[`Ref`]: https://doc.rust-lang.org/std/cell/struct.Ref.html
|
||||
[`RefMut`]: https://doc.rust-lang.org/std/cell/struct.RefMut.html
|
||||
|
||||
#### New `AnyUserDataExt` trait
|
||||
|
||||
Similar to the `TableExt` trait, the `AnyUserDataExt` provides a set of extra methods for the `AnyUserData` type.
|
||||
|
||||
1) `AnyUserDataExt::get()/set()` to get/set a value by key from the userdata, assuming it has `__index` metamethod.
|
||||
|
||||
2) `AnyUserDataExt::call()` to call the userdata as a function assuming it has `__call` metamethod.
|
||||
|
||||
3) `AnyUserData::call_method(name, ...)` to call the userdata method, assuming it has `__index` metamethod and the associated function.
|
||||
|
||||
#### Pretty formatting Lua values
|
||||
|
||||
`mlua::Value` implements a new format `:#?` that allows to (recursively) pretty print Lua values:
|
||||
|
||||
```rust
|
||||
println!("{:#?}", lua.globals());
|
||||
```
|
||||
|
||||
Prints:
|
||||
```
|
||||
{
|
||||
["_G"] = table: 0x7fa2d0706260,
|
||||
["_VERSION"] = "Lua 5.4",
|
||||
["assert"] = function: 0x10451d11d,
|
||||
["collectgarbage"] = function: 0x10451d198,
|
||||
["coroutine"] = {
|
||||
["close"] = function: 0x10451e28f,
|
||||
...
|
||||
},
|
||||
["dofile"] = function: 0x10451d37c,
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
In addition a new method `Value::to_string()` has been added to convert `Value` to a string (using `__tostring` metamethod if available).
|
||||
|
||||
#### Environment for Lua functions
|
||||
|
||||
Any Lua functions have an associated environment table that is used to resolve global variables. By default it sets to a Lua globals table.
|
||||
|
||||
In the new release it's possible to get or update a function environment using `Function::environment()` or `Function::set_environment()` methods respectively.
|
||||
|
||||
```rust
|
||||
let f = lua.load("return a").into_function()?;
|
||||
|
||||
assert_eq!(f.environment(), Some(lua.globals()));
|
||||
|
||||
lua.globals().set("a", 1)?;
|
||||
assert_eq!(f.call::<_, i32>(())?, 1);
|
||||
|
||||
f.set_environment(lua.create_table_from([("a", "hello")])?)?;
|
||||
assert_eq!(f.call::<_, mlua::String>(())?, "hello");
|
||||
```
|
||||
|
||||
#### Performance optimizations
|
||||
|
||||
The new mlua version has a number of performance improvements. Please check the [benchmarks results] to see how mlua compares to rlua and rhai.
|
||||
|
||||
[benchmarks results]: https://github.com/khvzak/script-bench-rs
|
||||
|
||||
### Changes in `module` mode
|
||||
|
||||
#### New attributes
|
||||
|
||||
The `lua_module` macro now support the following attributes:
|
||||
|
||||
- `name=...` - sets name of the module (defaults to the name of the function).
|
||||
|
||||
Eg.:
|
||||
|
||||
```rust
|
||||
#[mlua::lua_module(name = "alt_module")]
|
||||
fn my_module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
lua.create_table()
|
||||
}
|
||||
```
|
||||
|
||||
Under the hood a new function `luaopen_alt_module` will be created for the Lua module loader.
|
||||
|
||||
- `skip_memory_check` - skip memory allocation checks for some operations.
|
||||
|
||||
In module mode, mlua runs in unknown environment and cannot say are there any memory limits or not. As result, some operations that require memory allocation runs in
|
||||
protected mode. Setting this attribute will improve performance of such operations with risk of having uncaught exceptions and memory leaks.
|
||||
|
||||
#### Improved Windows target
|
||||
|
||||
In previous mlua versions, building a Lua module for Windows requires having Lua development libraries installed on the system.
|
||||
In contrast, on Linux and macOS, modules can be built without any external dependencies using the `-undefined=dynamic_lookup` linker flag.
|
||||
|
||||
With Rust 1.71+ it's now possible to lift this restriction for Windows as well. You can build modules normally and they will be linked with
|
||||
`lua54.dll`/`lua53.dll`/`lua52.dll`/`lua51.dll` depending on the enabled Lua version.
|
||||
|
||||
You still need to have the dll although, linked to application where the module will be loaded.
|
||||
|
||||
### Breaking changes
|
||||
|
||||
1) `ToLua`/`ToLuaMulti` traits have been renamed to `IntoLua`/`IntoLuaMulti` respectively (with the methods called `into_lua`/`into_lua_multi`).
|
||||
|
||||
The main reason for this change is following the Rust self [convention](https://rust-lang.github.io/rust-clippy/master/index.html#/wrong_self_convention).
|
||||
|
||||
2) Removed `FromLua` implementation for `T: UserData + Clone`.
|
||||
|
||||
During the usage of mlua, it was found that this implementation is not very useful and prevents custom `FromLua` implementations for `T: UserData`.
|
||||
It should be a developer decision to opt-in `FromLua` for their `T` if needed rather than having enabled it unconditionally.
|
||||
|
||||
To opt-in `FromLua` for `T: Clone` you can use a simple `#[derive(FromLua)]` macro (requires `feature = "macros"`):
|
||||
|
||||
```rust
|
||||
#[derive(Clone, Copy, mlua::FromLua)]
|
||||
struct MyUserData(i32);
|
||||
```
|
||||
|
||||
`T` is not required to implement `UserData` because of the new relaxed restrictions on userdata types.
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mlua-sys"
|
||||
version = "0.2.1"
|
||||
version = "0.3.0"
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>"]
|
||||
edition = "2021"
|
||||
repository = "https://github.com/khvzak/mlua"
|
||||
@@ -37,6 +37,6 @@ module = []
|
||||
cc = "1.0"
|
||||
cfg-if = "1.0"
|
||||
pkg-config = "0.3.17"
|
||||
lua-src = { version = ">= 546.0.0, < 550.0.0", optional = true }
|
||||
luajit-src = { version = ">= 210.4.5, < 220.0.0", optional = true }
|
||||
lua-src = { version = ">= 546.0.0, < 546.1.0", optional = true }
|
||||
luajit-src = { version = ">= 210.4.6, < 210.6.0", optional = true }
|
||||
luau0-src = { version = "0.5.11", optional = true }
|
||||
|
||||
@@ -1,91 +1,52 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::env;
|
||||
use std::ops::Bound;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn get_env_var(name: &str) -> String {
|
||||
match env::var(name) {
|
||||
Ok(val) => val,
|
||||
Err(env::VarError::NotPresent) => String::new(),
|
||||
Err(err) => panic!("cannot get {name}: {err}"),
|
||||
}
|
||||
}
|
||||
pub fn probe_lua() {
|
||||
let lib_dir = env::var("LUA_LIB").unwrap_or_default();
|
||||
let lua_lib = env::var("LUA_LIB_NAME").unwrap_or_default();
|
||||
|
||||
pub fn probe_lua() -> Option<PathBuf> {
|
||||
let include_dir = get_env_var("LUA_INC");
|
||||
let lib_dir = get_env_var("LUA_LIB");
|
||||
let lua_lib = get_env_var("LUA_LIB_NAME");
|
||||
|
||||
println!("cargo:rerun-if-env-changed=LUA_INC");
|
||||
println!("cargo:rerun-if-env-changed=LUA_LIB");
|
||||
println!("cargo:rerun-if-env-changed=LUA_LIB_NAME");
|
||||
println!("cargo:rerun-if-env-changed=LUA_LINK");
|
||||
|
||||
let need_lua_lib = cfg!(any(not(feature = "module"), target_os = "windows"));
|
||||
|
||||
if !include_dir.is_empty() {
|
||||
if need_lua_lib {
|
||||
if lib_dir.is_empty() {
|
||||
panic!("LUA_LIB is not set");
|
||||
}
|
||||
if lua_lib.is_empty() {
|
||||
panic!("LUA_LIB_NAME is not set");
|
||||
}
|
||||
|
||||
let mut link_lib = "";
|
||||
if get_env_var("LUA_LINK") == "static" {
|
||||
link_lib = "static=";
|
||||
};
|
||||
if !lua_lib.is_empty() {
|
||||
if !lib_dir.is_empty() {
|
||||
println!("cargo:rustc-link-search=native={lib_dir}");
|
||||
println!("cargo:rustc-link-lib={link_lib}{lua_lib}");
|
||||
}
|
||||
return Some(PathBuf::from(include_dir));
|
||||
let mut link_lib = "";
|
||||
if env::var("LUA_LINK").as_deref() == Ok("static") {
|
||||
link_lib = "static=";
|
||||
};
|
||||
println!("cargo:rustc-link-lib={link_lib}{lua_lib}");
|
||||
return;
|
||||
}
|
||||
|
||||
// Find using `pkg-config`
|
||||
|
||||
#[cfg(feature = "lua54")]
|
||||
let (incl_bound, excl_bound, alt_probe, ver) = ("5.4", "5.5", "lua5.4", "5.4");
|
||||
let (incl_bound, excl_bound, alt_probe, ver) = ("5.4", "5.5", Some("lua5.4"), "5.4");
|
||||
#[cfg(feature = "lua53")]
|
||||
let (incl_bound, excl_bound, alt_probe, ver) = ("5.3", "5.4", "lua5.3", "5.3");
|
||||
let (incl_bound, excl_bound, alt_probe, ver) = ("5.3", "5.4", Some("lua5.3"), "5.3");
|
||||
#[cfg(feature = "lua52")]
|
||||
let (incl_bound, excl_bound, alt_probe, ver) = ("5.2", "5.3", "lua5.2", "5.2");
|
||||
let (incl_bound, excl_bound, alt_probe, ver) = ("5.2", "5.3", Some("lua5.2"), "5.2");
|
||||
#[cfg(feature = "lua51")]
|
||||
let (incl_bound, excl_bound, alt_probe, ver) = ("5.1", "5.2", "lua5.1", "5.1");
|
||||
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
feature = "lua53",
|
||||
feature = "lua52",
|
||||
feature = "lua51"
|
||||
))]
|
||||
{
|
||||
let mut lua = pkg_config::Config::new()
|
||||
.range_version((Bound::Included(incl_bound), Bound::Excluded(excl_bound)))
|
||||
.cargo_metadata(need_lua_lib)
|
||||
.probe("lua");
|
||||
|
||||
if lua.is_err() {
|
||||
lua = pkg_config::Config::new()
|
||||
.cargo_metadata(need_lua_lib)
|
||||
.probe(alt_probe);
|
||||
}
|
||||
|
||||
lua.unwrap_or_else(|_| panic!("cannot find Lua {ver} using `pkg-config`"))
|
||||
.include_paths
|
||||
.get(0)
|
||||
.cloned()
|
||||
}
|
||||
|
||||
let (incl_bound, excl_bound, alt_probe, ver) = ("5.1", "5.2", Some("lua5.1"), "5.1");
|
||||
#[cfg(feature = "luajit")]
|
||||
{
|
||||
let lua = pkg_config::Config::new()
|
||||
.range_version((Bound::Included("2.0.4"), Bound::Unbounded))
|
||||
.cargo_metadata(need_lua_lib)
|
||||
.probe("luajit");
|
||||
let (incl_bound, excl_bound, alt_probe, ver) = ("2.0.4", "2.2", None, "JIT");
|
||||
|
||||
lua.expect("cannot find LuaJIT using `pkg-config`")
|
||||
.include_paths
|
||||
.get(0)
|
||||
.cloned()
|
||||
#[rustfmt::skip]
|
||||
let mut lua = pkg_config::Config::new()
|
||||
.range_version((Bound::Included(incl_bound), Bound::Excluded(excl_bound)))
|
||||
.cargo_metadata(true)
|
||||
.probe(if cfg!(feature = "luajit") { "luajit" } else { "lua" });
|
||||
|
||||
if lua.is_err() && alt_probe.is_some() {
|
||||
lua = pkg_config::Config::new()
|
||||
.cargo_metadata(true)
|
||||
.probe(alt_probe.unwrap());
|
||||
}
|
||||
|
||||
lua.unwrap_or_else(|err| panic!("cannot find Lua{ver} using `pkg-config`: {err}"));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::path::PathBuf;
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub fn probe_lua() -> Option<PathBuf> {
|
||||
pub fn probe_lua() {
|
||||
#[cfg(feature = "lua54")]
|
||||
let artifacts = lua_src::Build::new().build(lua_src::Lua54);
|
||||
|
||||
@@ -25,6 +25,4 @@ pub fn probe_lua() -> Option<PathBuf> {
|
||||
.build();
|
||||
|
||||
artifacts.print_cargo_metadata();
|
||||
|
||||
Some(artifacts.include_dir().to_owned())
|
||||
}
|
||||
|
||||
@@ -9,18 +9,25 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// We don't support "vendored module" mode on windows
|
||||
#[cfg(all(feature = "vendored", feature = "module", target_os = "windows"))]
|
||||
compile_error!(
|
||||
"Vendored (static) builds are not supported for modules on Windows.\n"
|
||||
+ "Please, use `pkg-config` or custom mode to link to a Lua dll."
|
||||
);
|
||||
|
||||
#[cfg(all(feature = "luau", feature = "module"))]
|
||||
compile_error!("Luau does not support module mode");
|
||||
compile_error!("Luau does not support `module` mode");
|
||||
|
||||
#[cfg(any(not(feature = "module"), target_os = "windows"))]
|
||||
find::probe_lua();
|
||||
#[cfg(all(feature = "module", feature = "vendored"))]
|
||||
compile_error!("`vendored` and `module` features are mutually exclusive");
|
||||
|
||||
println!("cargo:rerun-if-changed=build");
|
||||
|
||||
#[cfg(windows)]
|
||||
if cfg!(feature = "module") {
|
||||
if !std::env::var("LUA_LIB_NAME").unwrap_or_default().is_empty() {
|
||||
// Don't use raw-dylib linking
|
||||
find::probe_lua();
|
||||
return;
|
||||
}
|
||||
|
||||
println!("cargo:rustc-cfg=raw_dylib");
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "module"))]
|
||||
find::probe_lua();
|
||||
}
|
||||
|
||||
+1
-5
@@ -26,14 +26,10 @@ pub use luau::*;
|
||||
#[doc(hidden)]
|
||||
pub const LUA_MAX_UPVALUES: c_int = 255;
|
||||
|
||||
#[cfg(any(feature = "lua51", all(feature = "luajit", not(feature = "vendored"))))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[doc(hidden)]
|
||||
pub const LUA_MAX_UPVALUES: c_int = 60;
|
||||
|
||||
#[cfg(all(feature = "luajit", feature = "vendored"))]
|
||||
#[doc(hidden)]
|
||||
pub const LUA_MAX_UPVALUES: c_int = 120;
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
#[doc(hidden)]
|
||||
pub const LUA_MAX_UPVALUES: c_int = 200;
|
||||
|
||||
@@ -14,7 +14,8 @@ pub struct luaL_Reg {
|
||||
pub func: lua_CFunction,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua51", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaL_register(L: *mut lua_State, libname: *const c_char, l: *const luaL_Reg);
|
||||
#[link_name = "luaL_getmetafield"]
|
||||
pub fn luaL_getmetafield_(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
|
||||
@@ -56,7 +57,8 @@ extern "C" {
|
||||
pub const LUA_NOREF: c_int = -2;
|
||||
pub const LUA_REFNIL: c_int = -1;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua51", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaL_ref(L: *mut lua_State, t: c_int) -> c_int;
|
||||
pub fn luaL_unref(L: *mut lua_State, t: c_int, r#ref: c_int);
|
||||
|
||||
|
||||
+17
-17
@@ -73,23 +73,23 @@ pub type lua_Integer = i32;
|
||||
pub type lua_Integer = i64;
|
||||
|
||||
/// Type for native C functions that can be passed to Lua.
|
||||
pub type lua_CFunction = unsafe extern "C" fn(L: *mut lua_State) -> c_int;
|
||||
pub type lua_CFunction = unsafe extern "C-unwind" fn(L: *mut lua_State) -> c_int;
|
||||
|
||||
// Type for functions that read/write blocks when loading/dumping Lua chunks
|
||||
#[rustfmt::skip]
|
||||
pub type lua_Reader =
|
||||
unsafe extern "C" fn(L: *mut lua_State, ud: *mut c_void, sz: *mut usize) -> *const c_char;
|
||||
unsafe extern "C-unwind" fn(L: *mut lua_State, ud: *mut c_void, sz: *mut usize) -> *const c_char;
|
||||
#[rustfmt::skip]
|
||||
pub type lua_Writer =
|
||||
unsafe extern "C" fn(L: *mut lua_State, p: *const c_void, sz: usize, ud: *mut c_void) -> c_int;
|
||||
unsafe extern "C-unwind" fn(L: *mut lua_State, p: *const c_void, sz: usize, ud: *mut c_void) -> c_int;
|
||||
|
||||
/// Type for memory-allocation functions
|
||||
pub type lua_Alloc = unsafe extern "C" fn(
|
||||
ud: *mut c_void,
|
||||
ptr: *mut c_void,
|
||||
osize: usize,
|
||||
nsize: usize,
|
||||
) -> *mut c_void;
|
||||
#[rustfmt::skip]
|
||||
pub type lua_Alloc =
|
||||
unsafe extern "C-unwind" fn(ud: *mut c_void, ptr: *mut c_void, osize: usize, nsize: usize) -> *mut c_void;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua51", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// State manipulation
|
||||
//
|
||||
@@ -97,9 +97,6 @@ extern "C" {
|
||||
pub fn lua_close(L: *mut lua_State);
|
||||
pub fn lua_newthread(L: *mut lua_State) -> *mut lua_State;
|
||||
|
||||
#[cfg(all(feature = "luajit", feature = "vendored"))]
|
||||
pub fn lua_resetthread(L: *mut lua_State, th: *mut lua_State);
|
||||
|
||||
pub fn lua_atpanic(L: *mut lua_State, panicf: lua_CFunction) -> lua_CFunction;
|
||||
|
||||
//
|
||||
@@ -221,14 +218,16 @@ pub const LUA_GCSTEP: c_int = 5;
|
||||
pub const LUA_GCSETPAUSE: c_int = 6;
|
||||
pub const LUA_GCSETSTEPMUL: c_int = 7;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua51", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_gc(L: *mut lua_State, what: c_int, data: c_int) -> c_int;
|
||||
}
|
||||
|
||||
//
|
||||
// Miscellaneous functions
|
||||
//
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua51", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_error(L: *mut lua_State) -> !;
|
||||
pub fn lua_next(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_concat(L: *mut lua_State, n: c_int);
|
||||
@@ -351,9 +350,10 @@ pub const LUA_MASKLINE: c_int = 1 << (LUA_HOOKLINE as usize);
|
||||
pub const LUA_MASKCOUNT: c_int = 1 << (LUA_HOOKCOUNT as usize);
|
||||
|
||||
/// Type for functions to be called on debug events.
|
||||
pub type lua_Hook = unsafe extern "C" fn(L: *mut lua_State, ar: *mut lua_Debug);
|
||||
pub type lua_Hook = unsafe extern "C-unwind" fn(L: *mut lua_State, ar: *mut lua_Debug);
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua51", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_getstack(L: *mut lua_State, level: c_int, ar: *mut lua_Debug) -> c_int;
|
||||
pub fn lua_getinfo(L: *mut lua_State, what: *const c_char, ar: *mut lua_Debug) -> c_int;
|
||||
pub fn lua_getlocal(L: *mut lua_State, ar: *const lua_Debug, n: c_int) -> *const c_char;
|
||||
|
||||
@@ -20,7 +20,8 @@ pub const LUA_JITLIBNAME: &str = "jit";
|
||||
#[cfg(feature = "luajit")]
|
||||
pub const LUA_FFILIBNAME: &str = "ffi";
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua51", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaopen_base(L: *mut lua_State) -> c_int;
|
||||
pub fn luaopen_table(L: *mut lua_State) -> c_int;
|
||||
pub fn luaopen_io(L: *mut lua_State) -> c_int;
|
||||
|
||||
@@ -14,7 +14,8 @@ pub struct luaL_Reg {
|
||||
pub func: lua_CFunction,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua52", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaL_checkversion_(L: *mut lua_State, ver: lua_Number);
|
||||
|
||||
#[link_name = "luaL_getmetafield"]
|
||||
@@ -65,7 +66,8 @@ extern "C" {
|
||||
pub const LUA_NOREF: c_int = -2;
|
||||
pub const LUA_REFNIL: c_int = -1;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua52", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaL_ref(L: *mut lua_State, t: c_int) -> c_int;
|
||||
pub fn luaL_unref(L: *mut lua_State, t: c_int, r#ref: c_int);
|
||||
|
||||
@@ -78,7 +80,8 @@ pub unsafe fn luaL_loadfile(L: *mut lua_State, f: *const c_char) -> c_int {
|
||||
luaL_loadfilex(L, f, ptr::null())
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua52", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaL_loadbufferx(
|
||||
L: *mut lua_State,
|
||||
buff: *const c_char,
|
||||
|
||||
+24
-21
@@ -78,23 +78,23 @@ pub type lua_Integer = i64;
|
||||
pub type lua_Unsigned = c_uint;
|
||||
|
||||
/// Type for native C functions that can be passed to Lua
|
||||
pub type lua_CFunction = unsafe extern "C" fn(L: *mut lua_State) -> c_int;
|
||||
pub type lua_CFunction = unsafe extern "C-unwind" fn(L: *mut lua_State) -> c_int;
|
||||
|
||||
// Type for functions that read/write blocks when loading/dumping Lua chunks
|
||||
#[rustfmt::skip]
|
||||
pub type lua_Reader =
|
||||
unsafe extern "C" fn(L: *mut lua_State, ud: *mut c_void, sz: *mut usize) -> *const c_char;
|
||||
unsafe extern "C-unwind" fn(L: *mut lua_State, ud: *mut c_void, sz: *mut usize) -> *const c_char;
|
||||
#[rustfmt::skip]
|
||||
pub type lua_Writer =
|
||||
unsafe extern "C" fn(L: *mut lua_State, p: *const c_void, sz: usize, ud: *mut c_void) -> c_int;
|
||||
unsafe extern "C-unwind" fn(L: *mut lua_State, p: *const c_void, sz: usize, ud: *mut c_void) -> c_int;
|
||||
|
||||
/// Type for memory-allocation functions
|
||||
pub type lua_Alloc = unsafe extern "C" fn(
|
||||
ud: *mut c_void,
|
||||
ptr: *mut c_void,
|
||||
osize: usize,
|
||||
nsize: usize,
|
||||
) -> *mut c_void;
|
||||
#[rustfmt::skip]
|
||||
pub type lua_Alloc =
|
||||
unsafe extern "C-unwind" fn(ud: *mut c_void, ptr: *mut c_void, osize: usize, nsize: usize) -> *mut c_void;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua52", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// State manipulation
|
||||
//
|
||||
@@ -155,20 +155,19 @@ pub const LUA_OPMOD: c_int = 4;
|
||||
pub const LUA_OPPOW: c_int = 5;
|
||||
pub const LUA_OPUNM: c_int = 6;
|
||||
|
||||
extern "C" {
|
||||
pub fn lua_arith(L: *mut lua_State, op: c_int);
|
||||
}
|
||||
|
||||
pub const LUA_OPEQ: c_int = 0;
|
||||
pub const LUA_OPLT: c_int = 1;
|
||||
pub const LUA_OPLE: c_int = 2;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua52", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_arith(L: *mut lua_State, op: c_int);
|
||||
pub fn lua_rawequal(L: *mut lua_State, idx1: c_int, idx2: c_int) -> c_int;
|
||||
pub fn lua_compare(L: *mut lua_State, idx1: c_int, idx2: c_int, op: c_int) -> c_int;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua52", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// Push functions (C -> stack)
|
||||
//
|
||||
@@ -262,7 +261,8 @@ pub unsafe fn lua_pcall(L: *mut lua_State, n: c_int, r: c_int, f: c_int) -> c_in
|
||||
lua_pcallk(L, n, r, f, 0, None)
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua52", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// Coroutine functions
|
||||
//
|
||||
@@ -298,11 +298,13 @@ pub const LUA_GCISRUNNING: c_int = 9;
|
||||
pub const LUA_GCGEN: c_int = 10;
|
||||
pub const LUA_GCINC: c_int = 11;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua52", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_gc(L: *mut lua_State, what: c_int, data: c_int) -> c_int;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua52", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// Miscellaneous functions
|
||||
//
|
||||
@@ -437,9 +439,10 @@ pub const LUA_MASKLINE: c_int = 1 << (LUA_HOOKLINE as usize);
|
||||
pub const LUA_MASKCOUNT: c_int = 1 << (LUA_HOOKCOUNT as usize);
|
||||
|
||||
/// Type for functions to be called on debug events.
|
||||
pub type lua_Hook = unsafe extern "C" fn(L: *mut lua_State, ar: *mut lua_Debug);
|
||||
pub type lua_Hook = unsafe extern "C-unwind" fn(L: *mut lua_State, ar: *mut lua_Debug);
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua52", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_getstack(L: *mut lua_State, level: c_int, ar: *mut lua_Debug) -> c_int;
|
||||
pub fn lua_getinfo(L: *mut lua_State, what: *const c_char, ar: *mut lua_Debug) -> c_int;
|
||||
pub fn lua_getlocal(L: *mut lua_State, ar: *const lua_Debug, n: c_int) -> *const c_char;
|
||||
|
||||
@@ -14,7 +14,8 @@ pub const LUA_MATHLIBNAME: &str = "math";
|
||||
pub const LUA_DBLIBNAME: &str = "debug";
|
||||
pub const LUA_LOADLIBNAME: &str = "package";
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua52", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaopen_base(L: *mut lua_State) -> c_int;
|
||||
pub fn luaopen_coroutine(L: *mut lua_State) -> c_int;
|
||||
pub fn luaopen_table(L: *mut lua_State) -> c_int;
|
||||
|
||||
@@ -20,7 +20,8 @@ pub struct luaL_Reg {
|
||||
pub func: lua_CFunction,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaL_checkversion_(L: *mut lua_State, ver: lua_Number, sz: usize);
|
||||
|
||||
pub fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
|
||||
@@ -67,7 +68,8 @@ extern "C" {
|
||||
pub const LUA_NOREF: c_int = -2;
|
||||
pub const LUA_REFNIL: c_int = -1;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua53", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaL_ref(L: *mut lua_State, t: c_int) -> c_int;
|
||||
pub fn luaL_unref(L: *mut lua_State, t: c_int, r#ref: c_int);
|
||||
|
||||
@@ -80,7 +82,8 @@ pub unsafe fn luaL_loadfile(L: *mut lua_State, f: *const c_char) -> c_int {
|
||||
luaL_loadfilex(L, f, ptr::null())
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua53", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaL_loadbufferx(
|
||||
L: *mut lua_State,
|
||||
buff: *const c_char,
|
||||
|
||||
+25
-22
@@ -82,27 +82,27 @@ pub type lua_Unsigned = u64;
|
||||
pub type lua_KContext = isize;
|
||||
|
||||
/// Type for native C functions that can be passed to Lua
|
||||
pub type lua_CFunction = unsafe extern "C" fn(L: *mut lua_State) -> c_int;
|
||||
pub type lua_CFunction = unsafe extern "C-unwind" fn(L: *mut lua_State) -> c_int;
|
||||
|
||||
/// Type for continuation functions
|
||||
pub type lua_KFunction =
|
||||
unsafe extern "C" fn(L: *mut lua_State, status: c_int, ctx: lua_KContext) -> c_int;
|
||||
unsafe extern "C-unwind" fn(L: *mut lua_State, status: c_int, ctx: lua_KContext) -> c_int;
|
||||
|
||||
// Type for functions that read/write blocks when loading/dumping Lua chunks
|
||||
#[rustfmt::skip]
|
||||
pub type lua_Reader =
|
||||
unsafe extern "C" fn(L: *mut lua_State, ud: *mut c_void, sz: *mut usize) -> *const c_char;
|
||||
unsafe extern "C-unwind" fn(L: *mut lua_State, ud: *mut c_void, sz: *mut usize) -> *const c_char;
|
||||
#[rustfmt::skip]
|
||||
pub type lua_Writer =
|
||||
unsafe extern "C" fn(L: *mut lua_State, p: *const c_void, sz: usize, ud: *mut c_void) -> c_int;
|
||||
unsafe extern "C-unwind" fn(L: *mut lua_State, p: *const c_void, sz: usize, ud: *mut c_void) -> c_int;
|
||||
|
||||
/// Type for memory-allocation functions
|
||||
pub type lua_Alloc = unsafe extern "C" fn(
|
||||
ud: *mut c_void,
|
||||
ptr: *mut c_void,
|
||||
osize: usize,
|
||||
nsize: usize,
|
||||
) -> *mut c_void;
|
||||
#[rustfmt::skip]
|
||||
pub type lua_Alloc =
|
||||
unsafe extern "C-unwind" fn(ud: *mut c_void, ptr: *mut c_void, osize: usize, nsize: usize) -> *mut c_void;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua53", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// State manipulation
|
||||
//
|
||||
@@ -167,20 +167,19 @@ pub const LUA_OPSHR: c_int = 11;
|
||||
pub const LUA_OPUNM: c_int = 12;
|
||||
pub const LUA_OPBNOT: c_int = 13;
|
||||
|
||||
extern "C" {
|
||||
pub fn lua_arith(L: *mut lua_State, op: c_int);
|
||||
}
|
||||
|
||||
pub const LUA_OPEQ: c_int = 0;
|
||||
pub const LUA_OPLT: c_int = 1;
|
||||
pub const LUA_OPLE: c_int = 2;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua53", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_arith(L: *mut lua_State, op: c_int);
|
||||
pub fn lua_rawequal(L: *mut lua_State, idx1: c_int, idx2: c_int) -> c_int;
|
||||
pub fn lua_compare(L: *mut lua_State, idx1: c_int, idx2: c_int, op: c_int) -> c_int;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua53", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// Push functions (C -> stack)
|
||||
//
|
||||
@@ -270,7 +269,8 @@ pub unsafe fn lua_pcall(L: *mut lua_State, n: c_int, r: c_int, f: c_int) -> c_in
|
||||
lua_pcallk(L, n, r, f, 0, None)
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua53", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// Coroutine functions
|
||||
//
|
||||
@@ -304,11 +304,13 @@ pub const LUA_GCSETPAUSE: c_int = 6;
|
||||
pub const LUA_GCSETSTEPMUL: c_int = 7;
|
||||
pub const LUA_GCISRUNNING: c_int = 9;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua53", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_gc(L: *mut lua_State, what: c_int, data: c_int) -> c_int;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua53", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// Miscellaneous functions
|
||||
//
|
||||
@@ -461,9 +463,10 @@ pub const LUA_MASKLINE: c_int = 1 << (LUA_HOOKLINE as usize);
|
||||
pub const LUA_MASKCOUNT: c_int = 1 << (LUA_HOOKCOUNT as usize);
|
||||
|
||||
/// Type for functions to be called on debug events.
|
||||
pub type lua_Hook = unsafe extern "C" fn(L: *mut lua_State, ar: *mut lua_Debug);
|
||||
pub type lua_Hook = unsafe extern "C-unwind" fn(L: *mut lua_State, ar: *mut lua_Debug);
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua53", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_getstack(L: *mut lua_State, level: c_int, ar: *mut lua_Debug) -> c_int;
|
||||
pub fn lua_getinfo(L: *mut lua_State, what: *const c_char, ar: *mut lua_Debug) -> c_int;
|
||||
pub fn lua_getlocal(L: *mut lua_State, ar: *const lua_Debug, n: c_int) -> *const c_char;
|
||||
|
||||
@@ -15,7 +15,8 @@ pub const LUA_MATHLIBNAME: &str = "math";
|
||||
pub const LUA_DBLIBNAME: &str = "debug";
|
||||
pub const LUA_LOADLIBNAME: &str = "package";
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua53", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaopen_base(L: *mut lua_State) -> c_int;
|
||||
pub fn luaopen_coroutine(L: *mut lua_State) -> c_int;
|
||||
pub fn luaopen_table(L: *mut lua_State) -> c_int;
|
||||
|
||||
@@ -20,7 +20,8 @@ pub struct luaL_Reg {
|
||||
pub func: lua_CFunction,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaL_checkversion_(L: *mut lua_State, ver: lua_Number, sz: usize);
|
||||
|
||||
pub fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
|
||||
@@ -66,7 +67,8 @@ extern "C" {
|
||||
pub const LUA_NOREF: c_int = -2;
|
||||
pub const LUA_REFNIL: c_int = -1;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaL_ref(L: *mut lua_State, t: c_int) -> c_int;
|
||||
pub fn luaL_unref(L: *mut lua_State, t: c_int, r#ref: c_int);
|
||||
|
||||
@@ -79,7 +81,8 @@ pub unsafe fn luaL_loadfile(L: *mut lua_State, f: *const c_char) -> c_int {
|
||||
luaL_loadfilex(L, f, ptr::null())
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaL_loadbufferx(
|
||||
L: *mut lua_State,
|
||||
buff: *const c_char,
|
||||
|
||||
+28
-24
@@ -81,31 +81,31 @@ pub type lua_Unsigned = u64;
|
||||
pub type lua_KContext = isize;
|
||||
|
||||
/// Type for native C functions that can be passed to Lua
|
||||
pub type lua_CFunction = unsafe extern "C" fn(L: *mut lua_State) -> c_int;
|
||||
pub type lua_CFunction = unsafe extern "C-unwind" fn(L: *mut lua_State) -> c_int;
|
||||
|
||||
/// Type for continuation functions
|
||||
pub type lua_KFunction =
|
||||
unsafe extern "C" fn(L: *mut lua_State, status: c_int, ctx: lua_KContext) -> c_int;
|
||||
unsafe extern "C-unwind" fn(L: *mut lua_State, status: c_int, ctx: lua_KContext) -> c_int;
|
||||
|
||||
// Type for functions that read/write blocks when loading/dumping Lua chunks
|
||||
#[rustfmt::skip]
|
||||
pub type lua_Reader =
|
||||
unsafe extern "C" fn(L: *mut lua_State, ud: *mut c_void, sz: *mut usize) -> *const c_char;
|
||||
unsafe extern "C-unwind" fn(L: *mut lua_State, ud: *mut c_void, sz: *mut usize) -> *const c_char;
|
||||
#[rustfmt::skip]
|
||||
pub type lua_Writer =
|
||||
unsafe extern "C" fn(L: *mut lua_State, p: *const c_void, sz: usize, ud: *mut c_void) -> c_int;
|
||||
unsafe extern "C-unwind" fn(L: *mut lua_State, p: *const c_void, sz: usize, ud: *mut c_void) -> c_int;
|
||||
|
||||
/// Type for memory-allocation functions
|
||||
pub type lua_Alloc = unsafe extern "C" fn(
|
||||
ud: *mut c_void,
|
||||
ptr: *mut c_void,
|
||||
osize: usize,
|
||||
nsize: usize,
|
||||
) -> *mut c_void;
|
||||
#[rustfmt::skip]
|
||||
pub type lua_Alloc =
|
||||
unsafe extern "C-unwind" fn(ud: *mut c_void, ptr: *mut c_void, osize: usize, nsize: usize) -> *mut c_void;
|
||||
|
||||
/// Type for warning functions
|
||||
pub type lua_WarnFunction =
|
||||
unsafe extern "C" fn(ud: *mut c_void, msg: *const c_char, tocont: c_int);
|
||||
unsafe extern "C-unwind" fn(ud: *mut c_void, msg: *const c_char, tocont: c_int);
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// State manipulation
|
||||
//
|
||||
@@ -174,20 +174,19 @@ pub const LUA_OPSHR: c_int = 11;
|
||||
pub const LUA_OPUNM: c_int = 12;
|
||||
pub const LUA_OPBNOT: c_int = 13;
|
||||
|
||||
extern "C" {
|
||||
pub fn lua_arith(L: *mut lua_State, op: c_int);
|
||||
}
|
||||
|
||||
pub const LUA_OPEQ: c_int = 0;
|
||||
pub const LUA_OPLT: c_int = 1;
|
||||
pub const LUA_OPLE: c_int = 2;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_arith(L: *mut lua_State, op: c_int);
|
||||
pub fn lua_rawequal(L: *mut lua_State, idx1: c_int, idx2: c_int) -> c_int;
|
||||
pub fn lua_compare(L: *mut lua_State, idx1: c_int, idx2: c_int, op: c_int) -> c_int;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// Push functions (C -> stack)
|
||||
//
|
||||
@@ -277,7 +276,8 @@ pub unsafe fn lua_pcall(L: *mut lua_State, n: c_int, r: c_int, f: c_int) -> c_in
|
||||
lua_pcallk(L, n, r, f, 0, None)
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// Coroutine functions
|
||||
//
|
||||
@@ -305,7 +305,8 @@ pub unsafe fn lua_yield(L: *mut lua_State, n: c_int) -> c_int {
|
||||
//
|
||||
// Warning-related functions
|
||||
//
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_setwarnf(L: *mut lua_State, f: Option<lua_WarnFunction>, ud: *mut c_void);
|
||||
pub fn lua_warning(L: *mut lua_State, msg: *const c_char, tocont: c_int);
|
||||
}
|
||||
@@ -325,11 +326,13 @@ pub const LUA_GCISRUNNING: c_int = 9;
|
||||
pub const LUA_GCGEN: c_int = 10;
|
||||
pub const LUA_GCINC: c_int = 11;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_gc(L: *mut lua_State, what: c_int, ...) -> c_int;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// Miscellaneous functions
|
||||
//
|
||||
@@ -500,9 +503,10 @@ pub const LUA_MASKLINE: c_int = 1 << (LUA_HOOKLINE as usize);
|
||||
pub const LUA_MASKCOUNT: c_int = 1 << (LUA_HOOKCOUNT as usize);
|
||||
|
||||
/// Type for functions to be called on debug events.
|
||||
pub type lua_Hook = unsafe extern "C" fn(L: *mut lua_State, ar: *mut lua_Debug);
|
||||
pub type lua_Hook = unsafe extern "C-unwind" fn(L: *mut lua_State, ar: *mut lua_Debug);
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn lua_getstack(L: *mut lua_State, level: c_int, ar: *mut lua_Debug) -> c_int;
|
||||
pub fn lua_getinfo(L: *mut lua_State, what: *const c_char, ar: *mut lua_Debug) -> c_int;
|
||||
pub fn lua_getlocal(L: *mut lua_State, ar: *const lua_Debug, n: c_int) -> *const c_char;
|
||||
|
||||
@@ -14,7 +14,8 @@ pub const LUA_MATHLIBNAME: &str = "math";
|
||||
pub const LUA_DBLIBNAME: &str = "debug";
|
||||
pub const LUA_LOADLIBNAME: &str = "package";
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(all(windows, raw_dylib), link(name = "lua54", kind = "raw-dylib"))]
|
||||
extern "C-unwind" {
|
||||
pub fn luaopen_base(L: *mut lua_State) -> c_int;
|
||||
pub fn luaopen_coroutine(L: *mut lua_State) -> c_int;
|
||||
pub fn luaopen_table(L: *mut lua_State) -> c_int;
|
||||
|
||||
@@ -323,7 +323,7 @@ pub unsafe fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char)
|
||||
pub unsafe fn luaL_newmetatable(L: *mut lua_State, tname: *const c_char) -> c_int {
|
||||
if luaL_newmetatable_(L, tname) != 0 {
|
||||
lua_pushstring(L, tname);
|
||||
lua_setfield(L, -2, cstr!("__name"));
|
||||
lua_setfield(L, -2, cstr!("__type"));
|
||||
1
|
||||
} else {
|
||||
0
|
||||
@@ -341,7 +341,7 @@ pub unsafe fn luaL_loadbufferx(
|
||||
fn free(p: *mut c_void);
|
||||
}
|
||||
|
||||
let chunk_is_text = size == 0 || (*data as u8) >= b'\n';
|
||||
let chunk_is_text = size == 0 || (*data as u8) >= b'\t';
|
||||
if !mode.is_null() {
|
||||
let modeb = CStr::from_ptr(mode).to_bytes();
|
||||
if !chunk_is_text && !modeb.contains(&b'b') {
|
||||
@@ -454,7 +454,7 @@ pub unsafe fn luaL_tolstring(L: *mut lua_State, mut idx: c_int, len: *mut usize)
|
||||
}
|
||||
}
|
||||
t => {
|
||||
let tt = luaL_getmetafield(L, idx, cstr!("__name"));
|
||||
let tt = luaL_getmetafield(L, idx, cstr!("__type"));
|
||||
let name = if tt == LUA_TSTRING {
|
||||
lua_tostring(L, -1)
|
||||
} else {
|
||||
@@ -462,7 +462,7 @@ pub unsafe fn luaL_tolstring(L: *mut lua_State, mut idx: c_int, len: *mut usize)
|
||||
};
|
||||
lua_pushfstring(L, cstr!("%s: %p"), name, lua_topointer(L, idx));
|
||||
if tt != LUA_TNIL {
|
||||
lua_replace(L, -2); // remove '__name'
|
||||
lua_replace(L, -2); // remove '__type'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ pub struct luaL_Reg {
|
||||
pub func: lua_CFunction,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
extern "C-unwind" {
|
||||
pub fn luaL_register(L: *mut lua_State, libname: *const c_char, l: *const luaL_Reg);
|
||||
#[link_name = "luaL_getmetafield"]
|
||||
pub fn luaL_getmetafield_(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
|
||||
|
||||
+21
-21
@@ -69,15 +69,15 @@ pub type lua_Integer = c_int;
|
||||
pub type lua_Unsigned = c_uint;
|
||||
|
||||
/// Type for native C functions that can be passed to Lua.
|
||||
pub type lua_CFunction = unsafe extern "C" fn(L: *mut lua_State) -> c_int;
|
||||
pub type lua_Continuation = unsafe extern "C" fn(L: *mut lua_State, status: c_int) -> c_int;
|
||||
pub type lua_CFunction = unsafe extern "C-unwind" fn(L: *mut lua_State) -> c_int;
|
||||
pub type lua_Continuation = unsafe extern "C-unwind" fn(L: *mut lua_State, status: c_int) -> c_int;
|
||||
|
||||
/// Type for userdata destructor functions.
|
||||
pub type lua_Udestructor = unsafe extern "C" fn(*mut c_void);
|
||||
pub type lua_Destructor = unsafe extern "C" fn(L: *mut lua_State, *mut c_void);
|
||||
pub type lua_Udestructor = unsafe extern "C-unwind" fn(*mut c_void);
|
||||
pub type lua_Destructor = unsafe extern "C-unwind" fn(L: *mut lua_State, *mut c_void);
|
||||
|
||||
/// Type for memory-allocation functions.
|
||||
pub type lua_Alloc = unsafe extern "C" fn(
|
||||
pub type lua_Alloc = unsafe extern "C-unwind" fn(
|
||||
ud: *mut c_void,
|
||||
ptr: *mut c_void,
|
||||
osize: usize,
|
||||
@@ -89,7 +89,7 @@ pub const fn luau_version() -> Option<&'static str> {
|
||||
option_env!("LUAU_VERSION")
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
extern "C-unwind" {
|
||||
//
|
||||
// State manipulation
|
||||
//
|
||||
@@ -251,14 +251,14 @@ pub const LUA_GCSETGOAL: c_int = 7;
|
||||
pub const LUA_GCSETSTEPMUL: c_int = 8;
|
||||
pub const LUA_GCSETSTEPSIZE: c_int = 9;
|
||||
|
||||
extern "C" {
|
||||
extern "C-unwind" {
|
||||
pub fn lua_gc(L: *mut lua_State, what: c_int, data: c_int) -> c_int;
|
||||
}
|
||||
|
||||
//
|
||||
// Memory statistics
|
||||
//
|
||||
extern "C" {
|
||||
extern "C-unwind" {
|
||||
pub fn lua_setmemcat(L: *mut lua_State, category: c_int);
|
||||
pub fn lua_totalbytes(L: *mut lua_State, category: c_int) -> usize;
|
||||
}
|
||||
@@ -266,7 +266,7 @@ extern "C" {
|
||||
//
|
||||
// Miscellaneous functions
|
||||
//
|
||||
extern "C" {
|
||||
extern "C-unwind" {
|
||||
pub fn lua_error(L: *mut lua_State) -> !;
|
||||
pub fn lua_next(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_rawiter(L: *mut lua_State, idx: c_int, iter: c_int) -> c_int;
|
||||
@@ -286,7 +286,7 @@ extern "C" {
|
||||
pub const LUA_NOREF: c_int = -1;
|
||||
pub const LUA_REFNIL: c_int = 0;
|
||||
|
||||
extern "C" {
|
||||
extern "C-unwind" {
|
||||
pub fn lua_ref(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_unref(L: *mut lua_State, r#ref: c_int);
|
||||
}
|
||||
@@ -423,9 +423,9 @@ pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char {
|
||||
const LUA_IDSIZE: usize = 256;
|
||||
|
||||
/// Type for functions to be called on debug events.
|
||||
pub type lua_Hook = unsafe extern "C" fn(L: *mut lua_State, ar: *mut lua_Debug);
|
||||
pub type lua_Hook = unsafe extern "C-unwind" fn(L: *mut lua_State, ar: *mut lua_Debug);
|
||||
|
||||
pub type lua_Coverage = unsafe extern "C" fn(
|
||||
pub type lua_Coverage = unsafe extern "C-unwind" fn(
|
||||
context: *mut c_void,
|
||||
function: *const c_char,
|
||||
linedefined: c_int,
|
||||
@@ -434,7 +434,7 @@ pub type lua_Coverage = unsafe extern "C" fn(
|
||||
size: usize,
|
||||
);
|
||||
|
||||
extern "C" {
|
||||
extern "C-unwind" {
|
||||
pub fn lua_stackdepth(L: *mut lua_State) -> c_int;
|
||||
pub fn lua_getinfo(
|
||||
L: *mut lua_State,
|
||||
@@ -492,23 +492,23 @@ pub struct lua_Callbacks {
|
||||
pub userdata: *mut c_void,
|
||||
|
||||
/// gets called at safepoints (loop back edges, call/ret, gc) if set
|
||||
pub interrupt: Option<unsafe extern "C" fn(L: *mut lua_State, gc: c_int)>,
|
||||
pub interrupt: Option<unsafe extern "C-unwind" fn(L: *mut lua_State, gc: c_int)>,
|
||||
/// gets called when an unprotected error is raised (if longjmp is used)
|
||||
pub panic: Option<unsafe extern "C" fn(L: *mut lua_State, errcode: c_int)>,
|
||||
pub panic: Option<unsafe extern "C-unwind" fn(L: *mut lua_State, errcode: c_int)>,
|
||||
|
||||
/// gets called when L is created (LP == parent) or destroyed (LP == NULL)
|
||||
pub userthread: Option<unsafe extern "C" fn(LP: *mut lua_State, L: *mut lua_State)>,
|
||||
pub userthread: Option<unsafe extern "C-unwind" fn(LP: *mut lua_State, L: *mut lua_State)>,
|
||||
/// gets called when a string is created; returned atom can be retrieved via tostringatom
|
||||
pub useratom: Option<unsafe extern "C" fn(s: *const c_char, l: usize) -> i16>,
|
||||
pub useratom: Option<unsafe extern "C-unwind" fn(s: *const c_char, l: usize) -> i16>,
|
||||
|
||||
/// gets called when BREAK instruction is encountered
|
||||
pub debugbreak: Option<unsafe extern "C" fn(L: *mut lua_State, ar: *mut lua_Debug)>,
|
||||
pub debugbreak: Option<unsafe extern "C-unwind" fn(L: *mut lua_State, ar: *mut lua_Debug)>,
|
||||
/// gets called after each instruction in single step mode
|
||||
pub debugstep: Option<unsafe extern "C" fn(L: *mut lua_State, ar: *mut lua_Debug)>,
|
||||
pub debugstep: Option<unsafe extern "C-unwind" fn(L: *mut lua_State, ar: *mut lua_Debug)>,
|
||||
/// gets called when thread execution is interrupted by break in another thread
|
||||
pub debuginterrupt: Option<unsafe extern "C" fn(L: *mut lua_State, ar: *mut lua_Debug)>,
|
||||
pub debuginterrupt: Option<unsafe extern "C-unwind" fn(L: *mut lua_State, ar: *mut lua_Debug)>,
|
||||
/// gets called when protected call results in an error
|
||||
pub debugprotectederror: Option<unsafe extern "C" fn(L: *mut lua_State)>,
|
||||
pub debugprotectederror: Option<unsafe extern "C-unwind" fn(L: *mut lua_State)>,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -13,7 +13,7 @@ pub struct lua_CompileOptions {
|
||||
pub mutableGlobals: *mut *const c_char,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
extern "C-unwind" {
|
||||
#[link_name = "luau_compile"]
|
||||
pub fn luau_compile_(
|
||||
source: *const c_char,
|
||||
@@ -21,7 +21,9 @@ extern "C" {
|
||||
options: *mut lua_CompileOptions,
|
||||
outsize: *mut usize,
|
||||
) -> *mut c_char;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn free(p: *mut c_void);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::os::raw::c_int;
|
||||
|
||||
use super::lua::lua_State;
|
||||
|
||||
extern "C" {
|
||||
extern "C-unwind" {
|
||||
pub fn luau_codegen_supported() -> c_int;
|
||||
pub fn luau_codegen_create(state: *mut lua_State);
|
||||
pub fn luau_codegen_compile(state: *mut lua_State, idx: c_int);
|
||||
|
||||
@@ -13,7 +13,7 @@ pub const LUA_UTF8LIBNAME: &str = "utf8";
|
||||
pub const LUA_MATHLIBNAME: &str = "math";
|
||||
pub const LUA_DBLIBNAME: &str = "debug";
|
||||
|
||||
extern "C" {
|
||||
extern "C-unwind" {
|
||||
pub fn luaopen_base(L: *mut lua_State) -> c_int;
|
||||
pub fn luaopen_coroutine(L: *mut lua_State) -> c_int;
|
||||
pub fn luaopen_table(L: *mut lua_State) -> c_int;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mlua_derive"
|
||||
version = "0.9.0-rc.1"
|
||||
version = "0.9.0-rc.2"
|
||||
authors = ["Aleksandr Orlenko <zxteam@pm.me>"]
|
||||
edition = "2021"
|
||||
description = "Procedural macros for the mlua crate."
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
pub fn from_lua(input: TokenStream) -> TokenStream {
|
||||
let DeriveInput {
|
||||
ident, generics, ..
|
||||
} = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
let where_clause = match &generics.where_clause {
|
||||
Some(where_clause) => quote! { #where_clause, Self: 'static + Clone },
|
||||
None => quote! { where Self: 'static + Clone },
|
||||
};
|
||||
let ident_str = ident.to_string();
|
||||
|
||||
quote! {
|
||||
impl #generics ::mlua::FromLua<'_> for #ident #generics #where_clause {
|
||||
#[inline]
|
||||
fn from_lua(value: ::mlua::Value<'_>, lua: &'_ ::mlua::Lua) -> ::mlua::Result<Self> {
|
||||
match value {
|
||||
::mlua::Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
|
||||
_ => Err(::mlua::Error::FromLuaConversionError {
|
||||
from: value.type_name(),
|
||||
to: #ident_str,
|
||||
message: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
+19
-12
@@ -59,7 +59,7 @@ pub fn lua_module(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
#func
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn #ext_entrypoint_name(state: *mut ::mlua::lua_State) -> ::std::os::raw::c_int {
|
||||
unsafe extern "C-unwind" fn #ext_entrypoint_name(state: *mut ::mlua::lua_State) -> ::std::os::raw::c_int {
|
||||
let lua = ::mlua::Lua::init_from_ptr(state);
|
||||
if #skip_memory_check {
|
||||
lua.skip_memory_check(true);
|
||||
@@ -97,21 +97,20 @@ pub fn chunk(input: TokenStream) -> TokenStream {
|
||||
let wrapped_code = quote! {{
|
||||
use ::mlua::{AsChunk, ChunkMode, Lua, Result, Table};
|
||||
use ::std::borrow::Cow;
|
||||
use ::std::cell::Cell;
|
||||
use ::std::io::Result as IoResult;
|
||||
use ::std::sync::Mutex;
|
||||
use ::std::marker::PhantomData;
|
||||
|
||||
struct InnerChunk<F: for <'a> FnOnce(&'a Lua) -> Result<Table<'a>>>(Mutex<Option<F>>);
|
||||
struct InnerChunk<'lua, F: FnOnce(&'lua Lua) -> Result<Table<'lua>>>(Cell<Option<F>>, PhantomData<&'lua ()>);
|
||||
|
||||
impl<F> AsChunk<'static> for InnerChunk<F>
|
||||
impl<'lua, F> AsChunk<'lua, 'static> for InnerChunk<'lua, F>
|
||||
where
|
||||
F: for <'a> FnOnce(&'a Lua) -> Result<Table<'a>>,
|
||||
F: FnOnce(&'lua Lua) -> Result<Table<'lua>>,
|
||||
{
|
||||
fn environment<'lua>(&self, lua: &'lua Lua) -> Result<Option<Table<'lua>>> {
|
||||
fn environment(&self, lua: &'lua Lua) -> Result<Option<Table<'lua>>> {
|
||||
if #caps_len > 0 {
|
||||
if let Ok(mut make_env) = self.0.lock() {
|
||||
if let Some(make_env) = make_env.take() {
|
||||
return make_env(lua).map(Some);
|
||||
}
|
||||
if let Some(make_env) = self.0.take() {
|
||||
return make_env(lua).map(Some);
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
@@ -126,7 +125,7 @@ pub fn chunk(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
fn annotate<F: for<'a> FnOnce(&'a Lua) -> Result<Table<'a>>>(f: F) -> F { f }
|
||||
fn annotate<'a, F: FnOnce(&'a Lua) -> Result<Table<'a>>>(f: F) -> F { f }
|
||||
|
||||
let make_env = annotate(move |lua: &Lua| -> Result<Table> {
|
||||
let globals = lua.globals();
|
||||
@@ -142,13 +141,21 @@ pub fn chunk(input: TokenStream) -> TokenStream {
|
||||
Ok(env)
|
||||
});
|
||||
|
||||
InnerChunk(Mutex::new(Some(make_env)))
|
||||
InnerChunk(Cell::new(Some(make_env)), PhantomData)
|
||||
}};
|
||||
|
||||
wrapped_code.into()
|
||||
}
|
||||
|
||||
#[cfg(feature = "macros")]
|
||||
#[proc_macro_derive(FromLua)]
|
||||
pub fn from_lua(input: TokenStream) -> TokenStream {
|
||||
from_lua::from_lua(input)
|
||||
}
|
||||
|
||||
#[cfg(feature = "macros")]
|
||||
mod chunk;
|
||||
#[cfg(feature = "macros")]
|
||||
mod from_lua;
|
||||
#[cfg(feature = "macros")]
|
||||
mod token;
|
||||
|
||||
+10
-10
@@ -15,7 +15,7 @@ use crate::value::{FromLuaMulti, IntoLua, IntoLuaMulti};
|
||||
///
|
||||
/// [loadable by Lua]: https://www.lua.org/manual/5.4/manual.html#3.3.2
|
||||
/// [`Chunk`]: crate::Chunk
|
||||
pub trait AsChunk<'a> {
|
||||
pub trait AsChunk<'lua, 'a> {
|
||||
/// Returns optional chunk name
|
||||
fn name(&self) -> Option<StdString> {
|
||||
None
|
||||
@@ -24,7 +24,7 @@ pub trait AsChunk<'a> {
|
||||
/// Returns optional chunk [environment]
|
||||
///
|
||||
/// [environment]: https://www.lua.org/manual/5.4/manual.html#2.2
|
||||
fn environment<'lua>(&self, lua: &'lua Lua) -> Result<Option<Table<'lua>>> {
|
||||
fn environment(&self, lua: &'lua Lua) -> Result<Option<Table<'lua>>> {
|
||||
let _lua = lua; // suppress warning
|
||||
Ok(None)
|
||||
}
|
||||
@@ -38,43 +38,43 @@ pub trait AsChunk<'a> {
|
||||
fn source(self) -> IoResult<Cow<'a, [u8]>>;
|
||||
}
|
||||
|
||||
impl<'a> AsChunk<'a> for &'a str {
|
||||
impl<'a> AsChunk<'_, 'a> for &'a str {
|
||||
fn source(self) -> IoResult<Cow<'a, [u8]>> {
|
||||
Ok(Cow::Borrowed(self.as_ref()))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsChunk<'static> for StdString {
|
||||
impl AsChunk<'_, 'static> for StdString {
|
||||
fn source(self) -> IoResult<Cow<'static, [u8]>> {
|
||||
Ok(Cow::Owned(self.into_bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsChunk<'a> for &'a StdString {
|
||||
impl<'a> AsChunk<'_, 'a> for &'a StdString {
|
||||
fn source(self) -> IoResult<Cow<'a, [u8]>> {
|
||||
Ok(Cow::Borrowed(self.as_bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsChunk<'a> for &'a [u8] {
|
||||
impl<'a> AsChunk<'_, 'a> for &'a [u8] {
|
||||
fn source(self) -> IoResult<Cow<'a, [u8]>> {
|
||||
Ok(Cow::Borrowed(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsChunk<'static> for Vec<u8> {
|
||||
impl AsChunk<'_, 'static> for Vec<u8> {
|
||||
fn source(self) -> IoResult<Cow<'static, [u8]>> {
|
||||
Ok(Cow::Owned(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsChunk<'a> for &'a Vec<u8> {
|
||||
impl<'a> AsChunk<'_, 'a> for &'a Vec<u8> {
|
||||
fn source(self) -> IoResult<Cow<'a, [u8]>> {
|
||||
Ok(Cow::Borrowed(self.as_ref()))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsChunk<'static> for &Path {
|
||||
impl AsChunk<'_, 'static> for &Path {
|
||||
fn name(&self) -> Option<StdString> {
|
||||
Some(format!("@{}", self.display()))
|
||||
}
|
||||
@@ -84,7 +84,7 @@ impl AsChunk<'static> for &Path {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsChunk<'static> for PathBuf {
|
||||
impl AsChunk<'_, 'static> for PathBuf {
|
||||
fn name(&self) -> Option<StdString> {
|
||||
Some(format!("@{}", self.display()))
|
||||
}
|
||||
|
||||
+1
-19
@@ -9,7 +9,7 @@ use bstr::{BStr, BString};
|
||||
use num_traits::cast;
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
use crate::function::{Function, WrappedFunction};
|
||||
use crate::function::Function;
|
||||
use crate::lua::Lua;
|
||||
use crate::string::String;
|
||||
use crate::table::Table;
|
||||
@@ -21,9 +21,6 @@ use crate::value::{FromLua, IntoLua, Nil, Value};
|
||||
#[cfg(all(feature = "unstable", any(not(feature = "send"), doc)))]
|
||||
use crate::{function::OwnedFunction, table::OwnedTable, userdata::OwnedAnyUserData};
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
use crate::function::WrappedAsyncFunction;
|
||||
|
||||
impl<'lua> IntoLua<'lua> for Value<'lua> {
|
||||
#[inline]
|
||||
fn into_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
@@ -136,21 +133,6 @@ impl<'lua> FromLua<'lua> for OwnedFunction {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for WrappedFunction<'lua> {
|
||||
#[inline]
|
||||
fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
lua.create_callback(self.0).map(Value::Function)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
impl<'lua> IntoLua<'lua> for WrappedAsyncFunction<'lua> {
|
||||
#[inline]
|
||||
fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
lua.create_async_callback(self.0).map(Value::Function)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for Thread<'lua> {
|
||||
#[inline]
|
||||
fn into_lua(self, _: &'lua Lua) -> Result<Value<'lua>> {
|
||||
|
||||
+19
-4
@@ -13,7 +13,7 @@ use crate::util::{
|
||||
assert_stack, check_stack, error_traceback, linenumber_to_usize, pop_error, ptr_to_lossy_str,
|
||||
ptr_to_str, StackGuard,
|
||||
};
|
||||
use crate::value::{FromLuaMulti, IntoLua, IntoLuaMulti};
|
||||
use crate::value::{FromLuaMulti, IntoLua, IntoLuaMulti, Value};
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
use {
|
||||
@@ -228,7 +228,7 @@ impl<'lua> Function<'lua> {
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn bind<A: IntoLuaMulti<'lua>>(&self, args: A) -> Result<Function<'lua>> {
|
||||
unsafe extern "C" fn args_wrapper_impl(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C-unwind" fn args_wrapper_impl(state: *mut ffi::lua_State) -> c_int {
|
||||
let nargs = ffi::lua_gettop(state);
|
||||
let nbinds = ffi::lua_tointeger(state, ffi::lua_upvalueindex(1)) as c_int;
|
||||
ffi::luaL_checkstack(state, nbinds, ptr::null());
|
||||
@@ -423,7 +423,7 @@ impl<'lua> Function<'lua> {
|
||||
#[cfg(not(feature = "luau"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
|
||||
pub fn dump(&self, strip: bool) -> Vec<u8> {
|
||||
unsafe extern "C" fn writer(
|
||||
unsafe extern "C-unwind" fn writer(
|
||||
_state: *mut ffi::lua_State,
|
||||
buf: *const c_void,
|
||||
buf_len: usize,
|
||||
@@ -470,7 +470,7 @@ impl<'lua> Function<'lua> {
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
unsafe extern "C" fn callback<F: FnMut(CoverageInfo)>(
|
||||
unsafe extern "C-unwind" fn callback<F: FnMut(CoverageInfo)>(
|
||||
data: *mut c_void,
|
||||
function: *const c_char,
|
||||
line_defined: c_int,
|
||||
@@ -607,6 +607,21 @@ impl<'lua> Function<'lua> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for WrappedFunction<'lua> {
|
||||
#[inline]
|
||||
fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
lua.create_callback(self.0).map(Value::Function)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
impl<'lua> IntoLua<'lua> for WrappedAsyncFunction<'lua> {
|
||||
#[inline]
|
||||
fn into_lua(self, lua: &'lua Lua) -> Result<Value<'lua>> {
|
||||
lua.create_async_callback(self.0).map(Value::Function)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod assertions {
|
||||
use super::*;
|
||||
|
||||
+9
-1
@@ -216,6 +216,14 @@ pub use crate::{
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
|
||||
pub use mlua_derive::chunk;
|
||||
|
||||
/// Derive [`FromLua`] for a Rust type.
|
||||
///
|
||||
/// Current implementation generate code that takes [`UserData`] value, borrow it (of the Rust type)
|
||||
/// and clone.
|
||||
#[cfg(feature = "macros")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
|
||||
pub use mlua_derive::FromLua;
|
||||
|
||||
/// Registers Lua module entrypoint.
|
||||
///
|
||||
/// You can register multiple entrypoints as required.
|
||||
@@ -248,7 +256,7 @@ pub use mlua_derive::chunk;
|
||||
///
|
||||
/// In module mode, mlua runs in unknown environment and cannot say are there any memory
|
||||
/// limits or not. As result, some operations that require memory allocation runs in
|
||||
/// protected mode. Setting this mode will improve performance of such operations
|
||||
/// protected mode. Setting this attribute will improve performance of such operations
|
||||
/// with risk of having uncaught exceptions and memory leaks.
|
||||
///
|
||||
/// ```ignore
|
||||
|
||||
+23
-41
@@ -173,7 +173,7 @@ pub struct LuaOptions {
|
||||
|
||||
/// Max size of thread (coroutine) object pool used to execute asynchronous functions.
|
||||
///
|
||||
/// It works on Lua 5.4, LuaJIT (vendored) and Luau, where [`lua_resetthread`] function
|
||||
/// It works on Lua 5.4 and Luau, where [`lua_resetthread`] function
|
||||
/// is available and allows to reuse old coroutines after resetting their state.
|
||||
///
|
||||
/// Default: **0** (disabled)
|
||||
@@ -357,7 +357,7 @@ impl Lua {
|
||||
{
|
||||
// Workaround to avoid stripping a few unused Lua symbols that could be imported
|
||||
// by C modules in unsafe mode
|
||||
let mut _symbols: Vec<*const extern "C" fn()> = vec![
|
||||
let mut _symbols: Vec<*const extern "C-unwind" fn()> = vec![
|
||||
ffi::lua_atpanic as _,
|
||||
ffi::lua_isuserdata as _,
|
||||
ffi::lua_tocfunction as _,
|
||||
@@ -377,22 +377,14 @@ impl Lua {
|
||||
|
||||
/// Creates a new Lua state with required `libs` and `options`
|
||||
unsafe fn inner_new(libs: StdLib, options: LuaOptions) -> Lua {
|
||||
// Skip Rust allocator for non-vendored LuaJIT (see https://github.com/khvzak/mlua/issues/176)
|
||||
let use_rust_allocator = !(cfg!(feature = "luajit") && cfg!(not(feature = "vendored")));
|
||||
|
||||
let (state, mem_state) = if use_rust_allocator {
|
||||
let mut mem_state: *mut MemoryState = Box::into_raw(Box::default());
|
||||
let mut state = ffi::lua_newstate(ALLOCATOR, mem_state as *mut c_void);
|
||||
// If state is null (it's possible for LuaJIT on non-x86 arch) then switch to Lua internal allocator
|
||||
if state.is_null() {
|
||||
drop(Box::from_raw(mem_state));
|
||||
mem_state = ptr::null_mut();
|
||||
state = ffi::luaL_newstate();
|
||||
}
|
||||
(state, mem_state)
|
||||
} else {
|
||||
(ffi::luaL_newstate(), ptr::null_mut())
|
||||
};
|
||||
let mut mem_state: *mut MemoryState = Box::into_raw(Box::default());
|
||||
let mut state = ffi::lua_newstate(ALLOCATOR, mem_state as *mut c_void);
|
||||
// If state is null then switch to Lua internal allocator
|
||||
if state.is_null() {
|
||||
drop(Box::from_raw(mem_state));
|
||||
mem_state = ptr::null_mut();
|
||||
state = ffi::luaL_newstate();
|
||||
}
|
||||
assert!(!state.is_null(), "Failed to instantiate Lua VM");
|
||||
|
||||
ffi::luaL_requiref(state, cstr!("_G"), ffi::luaopen_base, 1);
|
||||
@@ -893,7 +885,7 @@ impl Lua {
|
||||
) where
|
||||
F: Fn(&Lua, Debug) -> Result<()> + MaybeSend + 'static,
|
||||
{
|
||||
unsafe extern "C" fn hook_proc(state: *mut ffi::lua_State, ar: *mut ffi::lua_Debug) {
|
||||
unsafe extern "C-unwind" fn hook_proc(state: *mut ffi::lua_State, ar: *mut ffi::lua_Debug) {
|
||||
let extra = extra_data(state);
|
||||
if (*extra).hook_thread != state {
|
||||
// Hook was destined for a different thread, ignore
|
||||
@@ -987,7 +979,7 @@ impl Lua {
|
||||
where
|
||||
F: Fn(&Lua) -> Result<VmState> + MaybeSend + 'static,
|
||||
{
|
||||
unsafe extern "C" fn interrupt_proc(state: *mut ffi::lua_State, gc: c_int) {
|
||||
unsafe extern "C-unwind" fn interrupt_proc(state: *mut ffi::lua_State, gc: c_int) {
|
||||
if gc >= 0 {
|
||||
// We don't support GC interrupts since they cannot survive Lua exceptions
|
||||
return;
|
||||
@@ -1039,7 +1031,7 @@ impl Lua {
|
||||
where
|
||||
F: Fn(&Lua, &str, bool) -> Result<()> + MaybeSend + 'static,
|
||||
{
|
||||
unsafe extern "C" fn warn_proc(ud: *mut c_void, msg: *const c_char, tocont: c_int) {
|
||||
unsafe extern "C-unwind" fn warn_proc(ud: *mut c_void, msg: *const c_char, tocont: c_int) {
|
||||
let extra = ud as *mut ExtraData;
|
||||
let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
|
||||
callback_error_ext(lua.state(), extra, |_| {
|
||||
@@ -1333,7 +1325,7 @@ impl Lua {
|
||||
///
|
||||
/// [`Chunk::exec`]: crate::Chunk::exec
|
||||
#[track_caller]
|
||||
pub fn load<'lua, 'a>(&'lua self, chunk: impl AsChunk<'a>) -> Chunk<'lua, 'a> {
|
||||
pub fn load<'lua, 'a>(&'lua self, chunk: impl AsChunk<'lua, 'a>) -> Chunk<'lua, 'a> {
|
||||
let caller = Location::caller();
|
||||
Chunk {
|
||||
lua: self,
|
||||
@@ -1673,11 +1665,7 @@ impl Lua {
|
||||
&'lua self,
|
||||
func: &Function,
|
||||
) -> Result<Thread<'lua>> {
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
all(feature = "luajit", feature = "vendored"),
|
||||
feature = "luau",
|
||||
))]
|
||||
#[cfg(any(feature = "lua54", feature = "luau"))]
|
||||
unsafe {
|
||||
let state = self.state();
|
||||
let _sg = StackGuard::new(state);
|
||||
@@ -1703,11 +1691,7 @@ impl Lua {
|
||||
|
||||
/// Resets thread (coroutine) and returns to the pool for later use.
|
||||
#[cfg(feature = "async")]
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
all(feature = "luajit", feature = "vendored"),
|
||||
feature = "luau",
|
||||
))]
|
||||
#[cfg(any(feature = "lua54", feature = "luau"))]
|
||||
pub(crate) unsafe fn recycle_thread(&self, thread: &mut Thread) -> bool {
|
||||
let extra = &mut *self.extra.get();
|
||||
if extra.thread_pool.len() < extra.thread_pool.capacity() {
|
||||
@@ -1721,8 +1705,6 @@ impl Lua {
|
||||
// Error object is on top, drop it
|
||||
ffi::lua_settop(thread_state, 0);
|
||||
}
|
||||
#[cfg(all(feature = "luajit", feature = "vendored"))]
|
||||
ffi::lua_resetthread(self.state(), thread_state);
|
||||
#[cfg(feature = "luau")]
|
||||
ffi::lua_resetthread(thread_state);
|
||||
extra.thread_pool.push(thread.0.index);
|
||||
@@ -2549,15 +2531,15 @@ impl Lua {
|
||||
}
|
||||
let mut has_name = false;
|
||||
for (k, f) in registry.meta_fields {
|
||||
has_name = has_name || k == "__name";
|
||||
has_name = has_name || k == MetaMethod::Type;
|
||||
self.push_value(f(self, MultiValue::new())?.pop_front().unwrap())?;
|
||||
rawset_field(state, -2, MetaMethod::validate(&k)?)?;
|
||||
}
|
||||
// Set `__name` if not provided
|
||||
// Set `__name/__type` if not provided
|
||||
if !has_name {
|
||||
let type_name = short_type_name::<T>();
|
||||
push_string(state, type_name.as_bytes(), !self.unlikely_memory_error())?;
|
||||
rawset_field(state, -2, "__name")?;
|
||||
rawset_field(state, -2, MetaMethod::Type.name())?;
|
||||
}
|
||||
let metatable_index = ffi::lua_absindex(state, -1);
|
||||
|
||||
@@ -2754,7 +2736,7 @@ impl Lua {
|
||||
&'lua self,
|
||||
func: Callback<'lua, 'static>,
|
||||
) -> Result<Function<'lua>> {
|
||||
unsafe extern "C" fn call_callback(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C-unwind" fn call_callback(state: *mut ffi::lua_State) -> c_int {
|
||||
// Normal functions can be scoped and therefore destroyed,
|
||||
// so we need to check that the first upvalue is valid
|
||||
let (upvalue, extra) = match ffi::lua_type(state, ffi::lua_upvalueindex(1)) {
|
||||
@@ -2832,7 +2814,7 @@ impl Lua {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn call_callback(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C-unwind" fn call_callback(state: *mut ffi::lua_State) -> c_int {
|
||||
// Async functions cannot be scoped and therefore destroyed,
|
||||
// so the first upvalue is always valid
|
||||
let upvalue = get_userdata::<AsyncCallbackUpvalue>(state, ffi::lua_upvalueindex(1));
|
||||
@@ -2865,7 +2847,7 @@ impl Lua {
|
||||
})
|
||||
}
|
||||
|
||||
unsafe extern "C" fn poll_future(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C-unwind" fn poll_future(state: *mut ffi::lua_State) -> c_int {
|
||||
let upvalue = get_userdata::<AsyncPollUpvalue>(state, ffi::lua_upvalueindex(1));
|
||||
let extra = (*upvalue).extra.get();
|
||||
callback_error_ext(state, extra, |_| {
|
||||
@@ -2921,7 +2903,7 @@ impl Lua {
|
||||
Function(self.pop_ref())
|
||||
};
|
||||
|
||||
unsafe extern "C" fn unpack(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C-unwind" fn unpack(state: *mut ffi::lua_State) -> c_int {
|
||||
let len = ffi::lua_tointeger(state, 2);
|
||||
ffi::luaL_checkstack(state, len as c_int, ptr::null());
|
||||
for i in 1..=len {
|
||||
|
||||
+2
-2
@@ -32,7 +32,7 @@ impl Lua {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn lua_collectgarbage(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C-unwind" fn lua_collectgarbage(state: *mut ffi::lua_State) -> c_int {
|
||||
let option = ffi::luaL_optstring(state, 1, cstr!("collect"));
|
||||
let option = CStr::from_ptr(option);
|
||||
let arg = ffi::luaL_optinteger(state, 2, 0);
|
||||
@@ -122,7 +122,7 @@ fn lua_require(lua: &Lua, name: Option<StdString>) -> Result<Value> {
|
||||
}
|
||||
|
||||
// Luau vector datatype constructor
|
||||
unsafe extern "C" fn lua_vector(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C-unwind" fn lua_vector(state: *mut ffi::lua_State) -> c_int {
|
||||
let x = ffi::luaL_checknumber(state, 1) as c_float;
|
||||
let y = ffi::luaL_checknumber(state, 2) as c_float;
|
||||
let z = ffi::luaL_checknumber(state, 3) as c_float;
|
||||
|
||||
+2
-1
@@ -101,7 +101,8 @@ macro_rules! protect_lua {
|
||||
};
|
||||
|
||||
($state:expr, $nargs:expr, $nresults:expr, fn($state_inner:ident) $code:expr) => {{
|
||||
unsafe extern "C" fn do_call($state_inner: *mut ffi::lua_State) -> ::std::os::raw::c_int {
|
||||
use ::std::os::raw::c_int;
|
||||
unsafe extern "C-unwind" fn do_call($state_inner: *mut ffi::lua_State) -> c_int {
|
||||
$code;
|
||||
let nresults = $nresults;
|
||||
if nresults == ::ffi::LUA_MULTRET {
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ impl MemoryState {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn allocator(
|
||||
unsafe extern "C-unwind" fn allocator(
|
||||
extra: *mut c_void,
|
||||
ptr: *mut c_void,
|
||||
osize: usize,
|
||||
|
||||
+6
-16
@@ -202,20 +202,16 @@ impl<'lua> Thread<'lua> {
|
||||
/// Returns a error in case of either the original error that stopped the thread or errors
|
||||
/// in closing methods.
|
||||
///
|
||||
/// In [LuaJIT] and Luau: resets to the initial state of a newly created Lua thread.
|
||||
/// In Luau: resets to the initial state of a newly created Lua thread.
|
||||
/// Lua threads in arbitrary states (like yielded or errored) can be reset properly.
|
||||
///
|
||||
/// Sets a Lua function for the thread afterwards.
|
||||
///
|
||||
/// Requires `feature = "lua54"` OR `feature = "luajit,vendored"` OR `feature = "luau"`
|
||||
/// Requires `feature = "lua54"` OR `feature = "luau"`.
|
||||
///
|
||||
/// [Lua 5.4]: https://www.lua.org/manual/5.4/manual.html#lua_resetthread
|
||||
/// [LuaJIT]: https://github.com/openresty/luajit2#lua_resetthread
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
all(feature = "luajit", feature = "vendored"),
|
||||
feature = "luau",
|
||||
))]
|
||||
/// [Lua 5.4]: https://www.lua.org/manual/5.4/manual.html#lua_closethread
|
||||
#[cfg(any(feature = "lua54", feature = "luau"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(not(feature = "luau"))))]
|
||||
pub fn reset(&self, func: crate::function::Function<'lua>) -> Result<()> {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
@@ -234,8 +230,6 @@ impl<'lua> Thread<'lua> {
|
||||
if status != ffi::LUA_OK {
|
||||
return Err(pop_error(thread_state, status));
|
||||
}
|
||||
#[cfg(all(feature = "luajit", feature = "vendored"))]
|
||||
ffi::lua_resetthread(state, thread_state);
|
||||
#[cfg(feature = "luau")]
|
||||
ffi::lua_resetthread(thread_state);
|
||||
|
||||
@@ -375,11 +369,7 @@ impl<'lua, R> AsyncThread<'lua, R> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
all(feature = "luajit", feature = "vendored"),
|
||||
feature = "luau",
|
||||
))]
|
||||
#[cfg(any(feature = "lua54", feature = "luau"))]
|
||||
impl<'lua, R> Drop for AsyncThread<'lua, R> {
|
||||
fn drop(&mut self) {
|
||||
if self.recycle {
|
||||
|
||||
+23
-3
@@ -1,5 +1,6 @@
|
||||
use std::any::{type_name, TypeId};
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::ffi::CStr;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::mem;
|
||||
@@ -36,6 +37,7 @@ pub(crate) const USER_VALUE_MAXSLOT: usize = 8;
|
||||
///
|
||||
/// [`UserData`]: crate::UserData
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[non_exhaustive]
|
||||
pub enum MetaMethod {
|
||||
/// The `+` operator.
|
||||
Add,
|
||||
@@ -141,6 +143,11 @@ pub enum MetaMethod {
|
||||
#[cfg(feature = "lua54")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "lua54")))]
|
||||
Close,
|
||||
/// The `__name`/`__type` metafield.
|
||||
///
|
||||
/// This is not a function, but it's value can be used by `tostring` and `typeof` built-in functions.
|
||||
#[doc(hidden)]
|
||||
Type,
|
||||
}
|
||||
|
||||
impl PartialEq<MetaMethod> for &str {
|
||||
@@ -212,6 +219,19 @@ impl MetaMethod {
|
||||
|
||||
#[cfg(feature = "lua54")]
|
||||
MetaMethod::Close => "__close",
|
||||
|
||||
#[rustfmt::skip]
|
||||
MetaMethod::Type => if cfg!(feature = "luau") { "__type" } else { "__name" },
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) const fn as_cstr(self) -> &'static CStr {
|
||||
match self {
|
||||
#[rustfmt::skip]
|
||||
MetaMethod::Type => unsafe {
|
||||
CStr::from_bytes_with_nul_unchecked(if cfg!(feature = "luau") { b"__type\0" } else { b"__name\0" })
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1089,7 +1109,7 @@ impl<'lua> AnyUserData<'lua> {
|
||||
unsafe { self.0.lua.get_userdata_type_id(&self.0) }
|
||||
}
|
||||
|
||||
/// Returns a type name of this `UserData` (from `__name` metatable field).
|
||||
/// Returns a type name of this `UserData` (from a metatable field).
|
||||
pub(crate) fn type_name(&self) -> Result<Option<StdString>> {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
@@ -1101,10 +1121,10 @@ impl<'lua> AnyUserData<'lua> {
|
||||
let protect = !lua.unlikely_memory_error();
|
||||
let name_type = if protect {
|
||||
protect_lua!(state, 1, 1, |state| {
|
||||
ffi::luaL_getmetafield(state, -1, cstr!("__name"))
|
||||
ffi::luaL_getmetafield(state, -1, MetaMethod::Type.as_cstr().as_ptr())
|
||||
})?
|
||||
} else {
|
||||
ffi::luaL_getmetafield(state, -1, cstr!("__name"))
|
||||
ffi::luaL_getmetafield(state, -1, MetaMethod::Type.as_cstr().as_ptr())
|
||||
};
|
||||
match name_type {
|
||||
ffi::LUA_TSTRING => Ok(Some(String(lua.pop_ref()).to_str()?.to_owned())),
|
||||
|
||||
+14
-14
@@ -88,7 +88,7 @@ impl Drop for StackGuard {
|
||||
pub unsafe fn protect_lua_call(
|
||||
state: *mut ffi::lua_State,
|
||||
nargs: c_int,
|
||||
f: unsafe extern "C" fn(*mut ffi::lua_State) -> c_int,
|
||||
f: unsafe extern "C-unwind" fn(*mut ffi::lua_State) -> c_int,
|
||||
) -> Result<()> {
|
||||
let stack_start = ffi::lua_gettop(state) - nargs;
|
||||
|
||||
@@ -133,7 +133,7 @@ where
|
||||
nresults: c_int,
|
||||
}
|
||||
|
||||
unsafe extern "C" fn do_call<F, R>(state: *mut ffi::lua_State) -> c_int
|
||||
unsafe extern "C-unwind" fn do_call<F, R>(state: *mut ffi::lua_State) -> c_int
|
||||
where
|
||||
F: Fn(*mut ffi::lua_State) -> R,
|
||||
R: Copy,
|
||||
@@ -295,7 +295,7 @@ pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T, protect: bool)
|
||||
#[cfg(feature = "luau")]
|
||||
#[inline]
|
||||
pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T, protect: bool) -> Result<()> {
|
||||
unsafe extern "C" fn destructor<T>(ud: *mut c_void) {
|
||||
unsafe extern "C-unwind" fn destructor<T>(ud: *mut c_void) {
|
||||
ptr::drop_in_place(ud as *mut T);
|
||||
}
|
||||
|
||||
@@ -400,16 +400,16 @@ pub unsafe fn get_gc_userdata<T: Any>(
|
||||
ud
|
||||
}
|
||||
|
||||
unsafe extern "C" fn lua_error_impl(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C-unwind" fn lua_error_impl(state: *mut ffi::lua_State) -> c_int {
|
||||
ffi::lua_error(state);
|
||||
}
|
||||
|
||||
unsafe extern "C" fn lua_isfunction_impl(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C-unwind" fn lua_isfunction_impl(state: *mut ffi::lua_State) -> c_int {
|
||||
ffi::lua_pushboolean(state, ffi::lua_isfunction(state, -1));
|
||||
1
|
||||
}
|
||||
|
||||
unsafe extern "C" fn lua_istable_impl(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C-unwind" fn lua_istable_impl(state: *mut ffi::lua_State) -> c_int {
|
||||
ffi::lua_pushboolean(state, ffi::lua_istable(state, -1));
|
||||
1
|
||||
}
|
||||
@@ -613,7 +613,7 @@ pub unsafe fn init_userdata_metatable(
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
pub unsafe extern "C" fn userdata_destructor<T>(state: *mut ffi::lua_State) -> c_int {
|
||||
pub unsafe extern "C-unwind" fn userdata_destructor<T>(state: *mut ffi::lua_State) -> c_int {
|
||||
// It's probably NOT a good idea to catch Rust panics in finalizer
|
||||
// Lua 5.4 ignores it, other versions generates `LUA_ERRGCMM` without calling message handler
|
||||
take_userdata::<T>(state);
|
||||
@@ -685,7 +685,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn error_traceback(state: *mut ffi::lua_State) -> c_int {
|
||||
pub unsafe extern "C-unwind" fn error_traceback(state: *mut ffi::lua_State) -> c_int {
|
||||
// Luau calls error handler for memory allocation errors, skip it
|
||||
// See https://github.com/Roblox/luau/issues/880
|
||||
#[cfg(feature = "luau")]
|
||||
@@ -725,7 +725,7 @@ pub unsafe fn error_traceback_thread(state: *mut ffi::lua_State, thread: *mut ff
|
||||
}
|
||||
|
||||
// A variant of `pcall` that does not allow Lua to catch Rust panics from `callback_error`.
|
||||
pub unsafe extern "C" fn safe_pcall(state: *mut ffi::lua_State) -> c_int {
|
||||
pub unsafe extern "C-unwind" fn safe_pcall(state: *mut ffi::lua_State) -> c_int {
|
||||
ffi::luaL_checkstack(state, 2, ptr::null());
|
||||
|
||||
let top = ffi::lua_gettop(state);
|
||||
@@ -751,8 +751,8 @@ pub unsafe extern "C" fn safe_pcall(state: *mut ffi::lua_State) -> c_int {
|
||||
}
|
||||
|
||||
// A variant of `xpcall` that does not allow Lua to catch Rust panics from `callback_error`.
|
||||
pub unsafe extern "C" fn safe_xpcall(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C" fn xpcall_msgh(state: *mut ffi::lua_State) -> c_int {
|
||||
pub unsafe extern "C-unwind" fn safe_xpcall(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C-unwind" fn xpcall_msgh(state: *mut ffi::lua_State) -> c_int {
|
||||
ffi::luaL_checkstack(state, 2, ptr::null());
|
||||
|
||||
if let Some(WrappedFailure::Panic(_)) =
|
||||
@@ -866,7 +866,7 @@ pub unsafe fn init_error_registry(state: *mut ffi::lua_State) -> Result<()> {
|
||||
|
||||
// Create error and panic metatables
|
||||
|
||||
unsafe extern "C" fn error_tostring(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C-unwind" fn error_tostring(state: *mut ffi::lua_State) -> c_int {
|
||||
callback_error(state, |_| {
|
||||
check_stack(state, 3)?;
|
||||
|
||||
@@ -924,7 +924,7 @@ pub unsafe fn init_error_registry(state: *mut ffi::lua_State) -> Result<()> {
|
||||
|
||||
// Create destructed userdata metatable
|
||||
|
||||
unsafe extern "C" fn destructed_error(state: *mut ffi::lua_State) -> c_int {
|
||||
unsafe extern "C-unwind" fn destructed_error(state: *mut ffi::lua_State) -> c_int {
|
||||
callback_error(state, |_| Err(Error::CallbackDestructed))
|
||||
}
|
||||
|
||||
@@ -1007,7 +1007,7 @@ impl WrappedFailure {
|
||||
let size = mem::size_of::<WrappedFailure>();
|
||||
#[cfg(feature = "luau")]
|
||||
let ud = {
|
||||
unsafe extern "C" fn destructor(p: *mut c_void) {
|
||||
unsafe extern "C-unwind" fn destructor(p: *mut c_void) {
|
||||
ptr::drop_in_place(p as *mut WrappedFailure);
|
||||
}
|
||||
ffi::lua_newuserdatadtor(state, size, destructor) as *mut Self
|
||||
|
||||
+1
-1
@@ -223,7 +223,7 @@ impl<'lua> Value<'lua> {
|
||||
f @ Value::Function(_) => write!(fmt, "function: {:?}", f.to_pointer()),
|
||||
t @ Value::Thread(_) => write!(fmt, "thread: {:?}", t.to_pointer()),
|
||||
u @ Value::UserData(ud) => {
|
||||
// Try `__name` first then `__tostring`
|
||||
// Try `__name/__type` first then `__tostring`
|
||||
let name = ud.type_name().ok().flatten();
|
||||
let s = name
|
||||
.map(|name| format!("{name}: {:?}", u.to_pointer()))
|
||||
|
||||
+13
-1
@@ -1,7 +1,7 @@
|
||||
use std::fs;
|
||||
use std::io;
|
||||
|
||||
use mlua::{Lua, Result};
|
||||
use mlua::{AnyUserData, Function, Lua, Result};
|
||||
|
||||
#[test]
|
||||
fn test_chunk_path() -> Result<()> {
|
||||
@@ -36,12 +36,24 @@ fn test_chunk_macro() -> Result<()> {
|
||||
let data = lua.create_table()?;
|
||||
data.raw_set("num", 1)?;
|
||||
|
||||
let ud = AnyUserData::wrap("hello");
|
||||
let f = Function::wrap(|_lua, ()| Ok(()));
|
||||
|
||||
lua.globals().set("g", 123)?;
|
||||
|
||||
let string = String::new();
|
||||
let str = string.as_str();
|
||||
|
||||
lua.load(mlua::chunk! {
|
||||
assert($name == "Rustacean")
|
||||
assert(type($table) == "table")
|
||||
assert($table[1] == 1)
|
||||
assert(type($data) == "table")
|
||||
assert($data.num == 1)
|
||||
assert(type($ud) == "userdata")
|
||||
assert(type($f) == "function")
|
||||
assert(type($str) == "string")
|
||||
assert($str == "")
|
||||
assert(g == 123)
|
||||
s = 321
|
||||
})
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ fn test_rust_function() -> Result<()> {
|
||||
fn test_c_function() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
unsafe extern "C" fn c_function(state: *mut mlua::lua_State) -> std::os::raw::c_int {
|
||||
unsafe extern "C-unwind" fn c_function(state: *mut mlua::lua_State) -> std::os::raw::c_int {
|
||||
let lua = Lua::init_from_ptr(state);
|
||||
lua.globals().set("c_function", true).unwrap();
|
||||
0
|
||||
|
||||
+4
-8
@@ -17,12 +17,8 @@ fn test_memory_limit() -> Result<()> {
|
||||
.into_function()?;
|
||||
f.call::<_, ()>(()).expect("should trigger no memory limit");
|
||||
|
||||
if cfg!(feature = "luajit") && cfg!(not(feature = "vendored")) {
|
||||
// we don't support setting memory limit for non-vendored luajit
|
||||
assert!(matches!(
|
||||
lua.set_memory_limit(0),
|
||||
Err(Error::MemoryLimitNotAvailable)
|
||||
));
|
||||
if cfg!(feature = "luajit") && lua.set_memory_limit(0).is_err() {
|
||||
// seems this luajit version does not support memory limit
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -46,8 +42,8 @@ fn test_memory_limit_thread() -> Result<()> {
|
||||
.load("local t = {}; for i = 1,10000 do t[i] = i end")
|
||||
.into_function()?;
|
||||
|
||||
if cfg!(feature = "luajit") && cfg!(not(feature = "vendored")) {
|
||||
// we don't support setting memory limit for non-vendored luajit
|
||||
if cfg!(feature = "luajit") && lua.set_memory_limit(0).is_err() {
|
||||
// seems this luajit version does not support memory limit
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
[target.x86_64-apple-darwin]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-undefined",
|
||||
"-C", "link-arg=dynamic_lookup",
|
||||
]
|
||||
|
||||
[target.aarch64-apple-darwin]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-undefined",
|
||||
"-C", "link-arg=dynamic_lookup",
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
fn main() {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
println!("cargo:rustc-cdylib-link-arg=-undefined");
|
||||
println!("cargo:rustc-cdylib-link-arg=dynamic_lookup");
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -69,7 +69,7 @@ fn test_safety() -> Result<()> {
|
||||
fn test_load() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
let func = lua.load("return 1+2").into_function()?;
|
||||
let func = lua.load("\treturn 1+2").into_function()?;
|
||||
let result: i32 = func.call(())?;
|
||||
assert_eq!(result, 3);
|
||||
|
||||
|
||||
+1
-5
@@ -94,11 +94,7 @@ fn test_thread() -> Result<()> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
all(feature = "luajit", feature = "vendored"),
|
||||
feature = "luau",
|
||||
))]
|
||||
#[cfg(any(feature = "lua54", feature = "luau"))]
|
||||
fn test_thread_reset() -> Result<()> {
|
||||
use mlua::{AnyUserData, UserData};
|
||||
use std::sync::Arc;
|
||||
|
||||
+49
-4
@@ -543,7 +543,7 @@ fn test_metatable() -> Result<()> {
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_function("my_type_name", |_, data: AnyUserData| {
|
||||
let metatable = data.get_metatable()?;
|
||||
metatable.get::<String>("__name")
|
||||
metatable.get::<String>(MetaMethod::Type)
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -554,6 +554,12 @@ fn test_metatable() -> Result<()> {
|
||||
lua.load(r#"assert(ud:my_type_name() == "MyUserData")"#)
|
||||
.exec()?;
|
||||
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "luau"))]
|
||||
lua.load(r#"assert(tostring(ud):sub(1, 11) == "MyUserData:")"#)
|
||||
.exec()?;
|
||||
#[cfg(feature = "luau")]
|
||||
lua.load(r#"assert(typeof(ud) == "MyUserData")"#).exec()?;
|
||||
|
||||
let ud: AnyUserData = globals.get("ud")?;
|
||||
let metatable = ud.get_metatable()?;
|
||||
|
||||
@@ -574,7 +580,7 @@ fn test_metatable() -> Result<()> {
|
||||
.map(|kv: Result<(_, Value)>| Ok(kv?.0))
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
methods.sort();
|
||||
assert_eq!(methods, vec!["__index", "__name"]);
|
||||
assert_eq!(methods, vec!["__index", MetaMethod::Type.name()]);
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct MyUserData2;
|
||||
@@ -596,13 +602,16 @@ fn test_metatable() -> Result<()> {
|
||||
|
||||
impl UserData for MyUserData3 {
|
||||
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_meta_field_with("__name", |_| Ok("CustomName"));
|
||||
fields.add_meta_field_with(MetaMethod::Type, |_| Ok("CustomName"));
|
||||
}
|
||||
}
|
||||
|
||||
let ud = lua.create_userdata(MyUserData3)?;
|
||||
let metatable = ud.get_metatable()?;
|
||||
assert_eq!(metatable.get::<String>("__name")?.to_str()?, "CustomName");
|
||||
assert_eq!(
|
||||
metatable.get::<String>(MetaMethod::Type)?.to_str()?,
|
||||
"CustomName"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -908,3 +917,39 @@ fn test_owned_userdata() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "macros")]
|
||||
#[test]
|
||||
fn test_userdata_derive() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
||||
// Simple struct
|
||||
|
||||
#[derive(Clone, Copy, mlua::FromLua)]
|
||||
struct MyUserData(i32);
|
||||
|
||||
lua.register_userdata_type::<MyUserData>(|reg| {
|
||||
reg.add_function("val", |_, this: MyUserData| Ok(this.0));
|
||||
})?;
|
||||
|
||||
lua.globals()
|
||||
.set("ud", AnyUserData::wrap(MyUserData(123)))?;
|
||||
lua.load("assert(ud:val() == 123)").exec()?;
|
||||
|
||||
// More complex struct where generics and where clause
|
||||
|
||||
#[derive(Clone, Copy, mlua::FromLua)]
|
||||
struct MyUserData2<'a, T>(&'a T)
|
||||
where
|
||||
T: ?Sized;
|
||||
|
||||
lua.register_userdata_type::<MyUserData2<'static, i32>>(|reg| {
|
||||
reg.add_function("val", |_, this: MyUserData2<'static, i32>| Ok(*this.0));
|
||||
})?;
|
||||
|
||||
lua.globals()
|
||||
.set("ud", AnyUserData::wrap(MyUserData2(&321)))?;
|
||||
lua.load("assert(ud:val() == 321)").exec()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user