ChangeLog | FAQ | Known issues
Ergonomic, efficient and Zero-cost rust bindings to Lua5.4
Features
- Serialization (serde) support
- Async function bindings support
- Ergonomic binding for functions and userdata methods
- Ergonomic stack values operation, you don't need to pay attention to the stack details
- Efficient: no auxiliary stack, support reference type conversion
- Builtin bindings to most commonly used rust std functions and types
- Mutilple thread support
- nostd support
Limits
- Nightly rust compiler needed (1.70+)
- Only support lua5.4 currently
Examples
Usage
Feature flags
async
: enable async/await support (any executor can be used, eg. [tokio] or [async-std])serde
: add serialization and deserialization support toezlua
types using [serde] frameworkvendored
: build static Lua library from sources duringezlua
compilation using [lua-src] cratesthread
enable the multiple thread supportstd
: enable the builtin bindings for rust std functions and typesjson
: enable the builtin bindings for [serde_json] crateregex
: enable the builtin bindings for [regex] crate
Basic
First, add ezlua to your dependencies in Cargo.toml
[]
= { = '0.3' }
Then, use ezlua in rust, the code framework like this
use *;
Bind your function
Of course, you can provide your rust function to lua via ezlua binding, and it's very simple, like this
lua.global.set?;
lua.do_string?;
And you can bind exists function easily
let string: LuaTable = lua.global.get?.try_into?;
string.set_closure?;
string.set_closure?;
string.set_closure?;
let os: LuaTable = lua.global.get?.try_into?;
os.set_closure?;
os.set_closure?;
os.set_closure?;
os.set_closure?;
os.set_closure?;
os.set_closure?;
Bind your type
Implement ToLua
trait for your type, and then you can pass it to lua
.global.set_closure?;
lua
Simply bindings via serde
Continuing with the example above, you can simply the binding code via serde
use ;
use SerdeValue;
// You can use impl_tolua_as_serde macro to simply this after version v0.3.1
// ezlua::impl_tolua_as_serde!(Config);
// You can use impl_fromlua_as_serde macro to simply this after version v0.3.1
// ezlua::impl_fromlua_as_serde!(Config);
lua.global.set?;
lua.global
.set_closure?;
Bind custom object (userdata)
ezlua's userdata binding mechanism is powerful, the following code comes from std bindings
use ;
Types impls the UserData
trait, ezlua also impls ToLua
for itself, and impls FromLua
for its reference
lua.global.set?;
Defaultly, types binded as userdata is immutable, if you need mutable reference, you can specific a UserData::Trans
type, and there is a builtin impl that is RefCell
, so the mutable binding impls looks like this
use RefCell;
use ;
Register your own module
To register a lua module, you can provide a rust function return a lua table via LuaState::register_module
method
lua.register_module?;
lua.register_module?;
And then use them in lua
local json = require
local path = require
local dir = path.
assert
Multiple thread usage
To use multiple thread feature in lua, you need to specify the thread
feature in Cargo.toml, and patch the lua-src crate with ezlua's custom
[]
= { = '0.3', = ['thread'] }
[]
= { = "https://github.com/metaworm/lua-src-rs" }
And then, register the thread module for lua
lua.register_module?;
And then, use it in lua
local thread = require
local threads =
local tt =
local count = 64
for i = 1, count
for i, t in ipairs
assert
In addition, you can also start a new thread with the same lua VM
let co = empty;
spawn
.join
.unwrap;
Module mode
In a module mode ezlua
allows to create a compiled Lua module that can be loaded from Lua code using require
.
First, disable the default vendored feature, and keep std feature only, and config your crate as a cdylib in Cargo.toml
:
[]
= { = '0.3', = false, = ['std']}
[]
= ['cdylib']
Then, export your luaopen_
function by using ezlua::lua_module!
macro, where the first argument is luaopen_<Your module name>
use *;
lua_module!;
Internal design
TODO