Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork175
High level Lua 5.4/5.3/5.2/5.1 (including LuaJIT) and Luau bindings to Rust with async/await support
License
mlua-rs/mlua
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
mlua
is a set of bindings to theLua programming language for Rust with a goal to provide asafe (as much as possible), high level, easy to use, practical and flexible API.
Started as anrlua
fork,mlua
supports Lua 5.4, 5.3, 5.2, 5.1 (including LuaJIT) andLuau and allows writing native Lua modules in Rust as well as using Lua in a standalone mode.
mlua
is tested on Windows/macOS/Linux including module mode inGitHub Actions onx86_64
platforms and cross-compilation toaarch64
(other targets are also supported).
WebAssembly (WASM) is supported throughwasm32-unknown-emscripten
target for all Lua/Luau versions excluding JIT.
mlua
uses feature flags to reduce the amount of dependencies and compiled code, and allow to choose only required set of features.Below is a list of the available feature flags. By defaultmlua
does not enable any features.
lua54
: enable Lua5.4 supportlua53
: enable Lua5.3 supportlua52
: enable Lua5.2 supportlua51
: enable Lua5.1 supportluajit
: enableLuaJIT supportluajit52
: enableLuaJIT support with partial compatibility with Lua 5.2luau
: enableLuau support (auto vendored mode)luau-jit
: enableLuau support with JIT backend.luau-vector4
: enableLuau support with 4-dimensional vector.vendored
: build static Lua(JIT) libraries from sources duringmlua
compilation usinglua-src orluajit-srcmodule
: enable module mode (building loadablecdylib
library for Lua)async
: enable async/await support (any executor can be used, eg.tokio orasync-std)send
: makemlua::Lua: Send + Sync
(addsSend
requirement tomlua::Function
andmlua::UserData
)error-send
: makemlua:Error: Send + Sync
serde
: add serialization and deserialization support tomlua
types usingserdemacros
: enable procedural macros (such aschunk!
)anyhow
: enableanyhow::Error
conversion into Luauserdata-wrappers
: opt intoimpl UserData
forRc<T>
/Arc<T>
/Rc<RefCell<T>>
/Arc<Mutex<T>>
whereT: UserData
mlua
supports async/await for all Lua versions including Luau.
This works using Luacoroutines and requires runningThread along with enablingfeature = "async"
inCargo.toml
.
Examples:
shell command examples:
# async http client (hyper)cargo run --example async_http_client --features=lua54,async,macros# async http client (reqwest)cargo run --example async_http_reqwest --features=lua54,async,macros,serde# async http servercargo run --example async_http_server --features=lua54,async,macros,sendcurl -v http://localhost:3000
With theserde
feature flag enabled,mlua
allows you to serialize/deserialize any type that implementsserde::Serialize
andserde::Deserialize
into/frommlua::Value
. In addition,mlua
provides theserde::Serialize
trait implementation formlua::Value
(includingUserData
support).
You have to enable one of the features:lua54
,lua53
,lua52
,lua51
,luajit(52)
orluau
, according to the chosen Lua version.
By defaultmlua
usespkg-config
to find Lua includes and libraries for the chosen Lua version.In most cases it works as desired, although sometimes it may be preferable to use a custom Lua library.To achieve this, mlua supports theLUA_LIB
,LUA_LIB_NAME
andLUA_LINK
environment variables.LUA_LINK
is optional and may bedylib
(a dynamic library) orstatic
(a static library,.a
archive).
An example of how to use them:
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 crateslua-src andluajit-src.Just enable thevendored
feature and cargo will automatically build and link the specified Lua/LuaJIT version. This is the easiest way to get started withmlua
.
In standalone mode,mlua
allows adding scripting support to your application with a gently configured Lua runtime to ensure safety and soundness.
Add toCargo.toml
:
[dependencies]mlua = {version ="0.11",features = ["lua54","vendored"] }
main.rs
use mlua::prelude::*;fnmain() ->LuaResult<()>{let lua =Lua::new();let map_table = lua.create_table()?; map_table.set(1,"one")?; map_table.set("two",2)?; lua.globals().set("map_table", map_table)?; lua.load("for k,v in pairs(map_table) do print(k,v) end").exec()?;Ok(())}
In module mode,mlua
allows creating a compiled Lua module that can be loaded from Lua code usingrequire
. In this casemlua
uses an external Lua runtime which could lead to potential unsafety due to the unpredictability of the Lua environment and usage of libraries such asdebug
.
Add toCargo.toml
:
[lib]crate-type = ["cdylib"][dependencies]mlua = {version ="0.11",features = ["lua54","module"] }
lib.rs
:
use mlua::prelude::*;fnhello(_:&Lua,name:String) ->LuaResult<()>{println!("hello, {}!", name);Ok(())}#[mlua::lua_module]fnmy_module(lua:&Lua) ->LuaResult<LuaTable>{let exports = lua.create_table()?; exports.set("hello", lua.create_function(hello)?)?;Ok(exports)}
And then (macOS example):
$ cargo rustc -- -C link-arg=-undefined -C link-arg=dynamic_lookup$ ln -s ./target/debug/libmy_module.dylib ./my_module.so$ lua5.4 -e'require("my_module").hello("world")'hello, world!
On macOS, you need to set additional linker arguments. One option is to compile withcargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup
, the other is to create a.cargo/config.toml
with the following content:
[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",]
On Linux you can build modules normally withcargo build --release
.
On Windows the target module will be linked with thelua5x.dll
library (depending on your feature flags).Your main application should provide this library.
Module builds don't require Lua binaries or headers to be installed on the system.
There is a LuaRocks build backend for mlua modules:luarocks-build-rust-mlua
.
Modules written in Rust and published to luarocks:
One ofmlua
's goals is to provide asafe API between Rust and Lua.Every place where the Lua C API may trigger an error longjmp is protected bylua_pcall
,and the user of the library is protected from directly interacting with unsafe things like the Lua stack.There is overhead associated with this safety.
Unfortunately,mlua
does not provide absolute safety even without usingunsafe
.This library contains a huge amount of unsafe code. There are almost certainly bugs still lurking in this library!It is surprisingly, fiendishly difficult to use the Lua C API without the potential for unsafety.
mlua
wraps panics that are generated inside Rust callbacks in a regular Lua error. Panics can then beresumed by returning or propagating the Lua error to Rust code.
For example:
let lua =Lua::new();let f = lua.create_function(|_,()| ->LuaResult<()>{panic!("test panic");})?;lua.globals().set("rust_func", f)?;let _ = lua.load(r#" local status, err = pcall(rust_func) print(err) -- prints: test panic error(err) -- propagate panic"#).exec();unreachable!()
Optionally,mlua
can disable Rust panic catching in Lua viapcall
/xpcall
and automatically resumethem across the Lua API boundary. This is controlled viaLuaOptions
and done by wrapping the Luapcall
/xpcall
functions to prevent catching errors that are wrapped Rust panics.
mlua
should also be panic safe in another way as well, which is that anyLua
instances or handlesremain usable after a user generated panic, and such panics should not break internal invariants orleak Lua stack space. This is mostly important to safely usemlua
types in Drop impls, as you should not beusing panics for general error handling.
Below is a list ofmlua
behaviors that should be considered a bug.If you encounter them, a bug report would be very welcome:
If you can cause UB with
mlua
without typing the word "unsafe", this is a bug.If your program panics with a message that contains the string "mlua internal error", this is a bug.
Lua C API errors are handled by longjmp. All instances where the Lua C API would otherwise longjmp over calling stack frames should be guarded against, except in internal callbacks where this is intentional. If you detect that
mlua
is triggering a longjmp over your Rust stack frames, this is a bug!If you detect that, after catching a panic or during a Drop triggered from a panic, a
Lua
or handle method is triggering other bugs or there is a Lua stack space leak, this is a bug.mlua
instances are supposed to remain fully usable in the face of user generated panics. This guarantee does not extend to panics marked with "mlua internal error" simply because that is already indicative of a separate bug.
Please check theLuau Sandboxing page if you are interested in running untrusted Lua scripts in a controlled environment.
mlua
provides theLua::sandbox
method for enabling sandbox mode (Luau only).
This project is licensed under theMIT license.
About
High level Lua 5.4/5.3/5.2/5.1 (including LuaJIT) and Luau bindings to Rust with async/await support
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Sponsor this project
Uh oh!
There was an error while loading.Please reload this page.