1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
//! 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 that can be loaded and ran from LuaJIT like any other Lua module.
//!
//! Check out the [examples directory] for some examples.
//!
//! # Tutorial
//!
//! *(Replace instances of `crate_name` with the name of your crate!)*
//!
//! To create your module's entry point, add a special function named `luaopen_crate_name`:
//!
//! ```
//! use low_luajit::{LuaState, AmountReturned};
//!
//! #[unsafe(no_mangle)]
//! extern "C-unwind" fn luaopen_crate_name(mut lua: LuaState) -> AmountReturned {
//! // ...
//! return lua.return_any(1); // Can be 0, but anything higher than 1 will be discarded.
//! }
//! ```
//!
//! This is the function that will be called when Lua loads your module.
//! It can return a value back to Lua which will be cached like any other module.
//!
//! While you can choose to return any value (including none), modules usually return a table of various functions your module can do.
//! `low_luajit` has some functions to ease this process:
//!
//! ```
//! use low_luajit::{LuaState, AmountReturned, reg};
//!
//! extern "C-unwind" fn foo(lua: LuaState) -> AmountReturned {
//! // ...
//! # AmountReturned::NONE
//! }
//!
//! extern "C-unwind" fn bar(lua: LuaState) -> AmountReturned {
//! // ...
//! # AmountReturned::NONE
//! }
//!
//! #[unsafe(no_mangle)]
//! extern "C-unwind" fn luaopen_crate_name(lua: LuaState) -> AmountReturned {
//! lua.return_module(reg![foo, bar])
//! }
//! ```
//!
//! This above code will have your module be returned as a table containing the functions `foo` and `bar`, that Lua can call directly!
//!
//! Once your module is ready to be compiled, make sure to configure your crate to be of type `cdylib`:
//!
//! ```toml
//! [package]
//! name = "crate_name"
//! # ...
//!
//! [lib]
//! crate-type = ["cdylib"]
//!
//! [dependencies]
//! low_luajit = "0.1"
//! # ...
//! ```
//!
//! And you're good to go!
//! Move the resulting library file (`.dll` on Windows, `.so` on Linux)
//! somewhere in the Lua code and you can now load and use your Rust library as a Lua module!
//!
//! ```lua
//! local crate_name = require("crate_name")
//!
//! crate_name.foo()
//! crate_name.bar()
//! ```
//!
//! To check out how you can interact with the LuaJIT API further to continue implementing your module, see [`LuaState`].
//!
//! For some example modules to use as reference, check out the [examples directory].
//!
//! ## Linux addendum
//!
//! When compiling dynamic libraries on Linux, Cargo adds a `lib` prefix to the outputted file (`libcrate_name.so`),
//! which trips Lua's default path solver.
//!
//! To resolve this, you can either modify the `package.cpath` variable:
//!
//! ```lua
//! package.cpath = "./lib?.so;" .. package.cpath
//! ```
//!
//! Or simply manually rename the file to `crate_name.so`.
//!
//! ## Windows addendum
//!
//! Windows is, for whatever reason, more strict on dynamic libraries, requiring symbols to be bound to a specific `.dll` name.
//!
//! The LuaJIT docs account for this:
//!
//! > Since Windows symbols are bound to a specific DLL name,
//! > you need to link to the lua51.dll created by the LuaJIT build (do not rename the DLL).
//! > You may link LuaJIT statically on Windows only if you don't intend to load Lua/C modules at runtime.
//!
//! Following this, when compiling on Windows the symbols are binded to `lua51.dll`,
//! which should work for any program that is compliant with the LuaJIT docs and intends to allow loading external modules at runtime.
//!
//! # Error handling
//!
//! When Lua errors, the error is propagated upwards using a long jump,
//! unwinding through any Rust or Lua code until it's caught by the protected environment
//! (where it will be handled by whoever created said environment).
//!
//! *(You can create protected environments using [`LuaState::pcall`] or [`LuaState::cpcall`].)*
//!
//! If a long jump happens, any running Rust function will be left unfinished (any variable left will not be dropped),
//! but it shouldn't cause any undefined behavior.
//!
//! When Lua errors outside of a protected environment, Rust should be able to catch the error and abort
//! (though Lua programs normally always run within a protected environment).
//!
//! Rust panics behave mostly as usual, just often failing to fully unwind and thus aborting instead, which should be harmless.
//!
//! Functions that may trigger Lua errors will clarify the error conditions in their description.
//! *(Except unlikely but possible stack/table overflows,
//! just assume that any function that adds more elements without removing some can overflow if called many many times.)*
//!
//! If a function may trigger a Lua error in an undocumented way, let me know and I'll add the missing docs!
//!
//! # Planned features
//!
//! The main objective is a wrapper for the LuaJIT C API that tries to strike a good (but subjective) balance between lightweight and safe.
//! Some C functions/types still need to be safely exposed currently.
//!
//! Following that, some slightly higher level utilities to ease some important yet repetitive tasks could be added,
//! but they would still have to directly interact with the LuaJIT C API, with little overhead; a few ideas could be:
//! - Simple iterator structs that just call the functions needed to properly iterate a table for you.
//! - Potentially a safe way to use this library to just run LuaJIT within Rust instead (currently only possible via [`ffi`])?
//! - Safe versions of the functions that can panic (or alternatively a safe wrapper around any function/closure)?
//!
//! If you'd like to create high level bindings instead, feel free to use this library as your base/dependency!
//! *Just follow the license...*
//!
//! [examples directory]: https://git.blossomdevs.com/Rosy.iso/low-luajit/src/branch/main/examples
/// Internal auxiliary macro for mapping pointers to an `Option`.
pub use map_ptr;
/// Auxiliary conversion methods for [`CFunction`] and [`Hook`].
///
/// *([`CFunction`] and [`Hook`] are simple type definitions, so methods can't be implemented directly...)*
pub use ;