- Rust 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| examples | ||
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
low-luajit
A lightweight library that aims to add low level but safe (as much as possible) bindings to the LuaJIT C API with no dependencies and no-std support.
These bindings can be used to create dynamic Rust libraries (.dll/.so) that can be loaded and ran from LuaJIT like any other Lua module.
use low_luajit::{LuaState, AmountReturned};
extern "C-unwind" fn multiply(mut lua: LuaState) -> AmountReturned {
let x = lua.check_number(1);
let y = lua.check_number(2);
lua.return_number(x * y);
}
#[unsafe(no_mangle)]
extern "C-unwind" fn luaopen_mymodule(mut lua: LuaState) -> AmountReturned {
lua.return_cfunction(multiply)
}
local multiply = require("mymodule")
print(multiply(52, 196))
For more information, check out the documentation and the examples directory.
Compatibility & Maintenance
This library is used internally for BlossomDevs games, so it should stay maintained for at least a very long time. Version 1.0 will be reached once things feel stable, comfortable and tested enough.
LuaJIT wise, the objective is currently to support v2.0 and v2.1's LuaJIT C API, as it should not receive any breaking changes. If LuaJIT v3.0 is released...support will be added based on the severity of the breaking changes (most likely via a cargo feature).
Anything LuaJIT officially supports (i.e. which devices and CPU architectures are supported) should be compatible. While anything not officially supported will be disregarded and may or may not be compatible.
Why only official LuaJIT?
Simply because it's the Lua I personally use and know best, I wouldn't feel qualified to add proper support for anything else.
Feel free to fork low-luajit and create your own library to support other versions/variants of Lua if needed!
(Just remember to follow the licensing conditions...)
Safety policy
Ideally, every safe function in this library should not directly cause any undefined behavior (excluding external factors coming from Lua itself, like an unsafe metamethod being triggered or a function using the ffi library).
Additionally, it should be reasonably safe for the users of your module to use it and its output. (LuaJIT itself is not fully safe so at worst your module is as unsafe as any Lua module can be...)
Since the LuaJIT C API is rather unsafe, there could sadly always be some unsafe bug hidden somewhere. Report any such bug and I'll try to fix it right away!
If needed, it's possible to access the raw unsafe LuaJIT C API directly via the ffi module.
Alternatives
Below are alternatives to low-luajit alongside non-exhaustive lists of differences I've noted.
mlua
mlua is a set of high level bindings to all sorts of Lua versions (including LuaJIT),
with its own custom Rust-like API that does all the inner workings for you as safely as possible.
low-luajitprefers to give you direct access to the C API itself (safely): while inmluamost functions tend to have quite the overhead (imo) of extra stuff inbetween you and the C API, mostlow-luajitmethods map directly to one (sometimes more than one) C API function with as little overhead as needed to make it safe.- Since
mluahas a far grander scope, it also has a (relatively) larger size: it has ~9x more source lines of code and the package is ~6x larger. - Safety wise, things are overall the same: most the unsafety comes from the Lua side of things. (We can't control what the Lua code does!)
- While
mluasupports LuaJIT, it does not have access to any of the extensions the LuaJIT C API has over the Lua C API.low-luajitinstead supports the entire LuaJIT C API (safe versions of some of the extensions are currently WIP). low-luajithas a far simpler and more purely functional API whilemluaoffers a more advanced high level API.mluasupports async/await.low-luajitcurrently does not.mluasupports serializing/deserializing any supporting type into Lua values.low-luajitinstead just lets you push/pop and read Lua values directly from the stack.mluais licensed under the MIT license, which requires including the copyright and permission notice in all derivative works.low-luajitis instead licensed under the Boost Software License, which (while similar) allows sharing derivative works with no requirements when only the binary is shared. (See the licenses for more info, I'm not a lawyer and can't give legal advice.)
While both libraries can be used for the same objective, they do so in very different but equally valid ways. I do not believe either is "superior" to the other, instead I recommend doing your personal comparisons to find which one fits your needs.
LuaJIT's ffi library
The ffi library provided by LuaJIT allows calling external C functions or using C data structures from within Lua itself,
by simply parsing plain C declarations.
- It's already included in LuaJIT, so you wouldn't need to install it.
ffiinterfaces with C code, not Rust code: you'll have to manually keep your bindings safe!- While modules made in
low-luajitare shared as a single dynamic library (.dll/.so), modules created withffiwill need to include an additional.luafile that contains the bindings themselves. - The C API is unavailable to
ffi, which greatly alters how interactions with Lua happen: instead of your module having direct access to the values sent by Lua, said values will instead have to be converted to C values before they can be passed. (A major example is that you have no direct access to tables, they would all need to be converted to either an array or a struct with predefined fields.) low-luajit's performance compared toffiwould depend on how often the C API gets called, which will be different for every module and every function: if the module heavily relies on the C API often, it might result in less performance thanffi; on the other hand, if the module has an average usage of the C API (like simply getting the parameters and returning the results), it could even outperformffi. (Do note that both LuaJIT and C/Rust are really fast all the time, the speed difference will likely be very negligible either way!)
Overall, low-luajit and the ffi library are very different in how they operate, but either could be used to create your module in their own way.
The main thing to consider is if you'd rather interface with Lua by using the C API or by effectively creating your own custom interface.
Licensing
Copyright © 2026 Rosy.iso rosy.iso@blossomdevs.com
This library is licensed under the Boost Software License.
Contributing
Currently, feel free to email me (or send via any other means) a patch to contribute!
If enough people seem interested in this library, I will host a mirror on codeberg.
All contributions are assumed to be under the same license as the repository itself and must contain no AI generated/"assisted" code whatsoever.