Overview
lua wraps liblua5.4 — a lightweight, fast, embeddable scripting language designed to be hosted inside applications written in other languages. It gives your PascalAI program a full Lua 5.4 interpreter: execute scripts, call named functions, exchange typed globals, access table fields, register host callbacks, and run untrusted code inside a tight instruction-count and memory sandbox.
Lua's stack-based C API is one of the cleanest embedding interfaces in any scripting language. This package surfaces it as straightforward PascalAI calls so you never need to touch the raw API yourself.
CLib package
Requires liblua5.4-dev. Ubuntu/Debian: sudo apt install liblua5.4-dev
Key Characteristics
| Property | Detail |
| Size | ~300 KB compiled library — smallest production-grade scripting engine |
| Speed | Fastest interpreted language in most benchmarks; register-based VM |
| Memory | Precise GC with both incremental and generational modes |
| Coroutines | Native cooperative multitasking via coroutine.* |
| Tables | Universal data structure: arrays, maps, objects, modules — all one type |
| Metatables | Operator overloading, OOP, custom metamethods without special syntax |
| C API | Simple stack-based interface; register any host function callable from Lua |
Lua 5.4 Features
| Feature | Description |
| Integer type | Separate int64 and float64 types; integer arithmetic no longer goes through float |
| Generational GC | New generational collection mode for faster minor GC pauses on short-lived objects |
| Const / close vars | <const> attribute prevents reassignment; <close> enables to-be-closed variables (RAII in Lua) |
Used By
| Project | How Lua is used |
| Redis | Server-side scripting with EVAL — millions of scripts run daily |
| nginx / OpenResty | Full web application framework built on top of embedded Lua |
| World of Warcraft | All UI addons and game logic written in Lua |
| Factorio | Entire game modding API; mods are plain Lua scripts |
| Wireshark | Protocol dissectors and post-analysis scripts |
| VLC | Extensions, interface scripts, playlist parsers |
| Nmap | NSE (Nmap Scripting Engine) for port and service detection |
| Adobe Lightroom | Plugin API and automation scripts |
| LOVE2D | Full 2D game framework where every game is a Lua program |
Comparison
| vs. | Verdict |
| Python | Lua is 10–100x smaller and significantly faster to embed; Python carries a large runtime |
| QuickJS (JS) | Similar binary size; Lua has a simpler, more stable C API and a longer embedding track record |
| Wren | Lua has a vastly larger ecosystem, more tooling, and battle-tested production deployments |
Quick Start
Execute a Lua script
uses lua;
var L := NewState();
var err := ExecString(L, 'print("Hello from Lua!")');
if err <> '' then
WriteLn('Lua error: ' + err);
CloseState(L);
Call a Lua function from PascalAI
uses lua;
var L := NewState();
{ Define a Lua function }
ExecString(L, 'function greet(name) return "Hello, " .. name .. "!" end');
{ Call it with arguments }
var result := CallFunc(L, 'greet', ['PascalAI']);
WriteLn(result); { Hello, PascalAI! }
CloseState(L);
Exchange global variables
uses lua;
var L := NewState();
{ Push values into Lua }
SetGlobalString(L, 'user', 'alice');
SetGlobalNumber(L, 'score', 42.5);
SetGlobalBool(L, 'active', True);
ExecString(L, 'result = user .. " scored " .. score');
{ Pull values back out }
var msg := GetGlobalString(L, 'result');
WriteLn(msg); { alice scored 42.5 }
CloseState(L);
Sandboxed eval
uses lua;
{ Bare state has no io, os, or other dangerous libraries }
var L := NewBareState();
OpenSafeLibs(L); { math, string, table only }
{ Limit: 1 million instructions, 4 MB memory }
SetInstructionLimit(L, 1000000);
SetMemoryLimit(L, 4 * 1024 * 1024);
var val := EvalNumber(L, 'math.sqrt(144)');
WriteLn(FloatToStr(val)); { 12.0 }
CloseState(L);
Types
| Type | Description |
| TLuaState | Handle to a Lua interpreter instance. All API calls take this as the first argument. |
| TLuaType | Enumeration of Lua value types returned by GetGlobalType. |
| TLuaGCMode | Garbage collector control modes passed to GC(). |
State Lifecycle
Every embedding session starts with a state and must end with CloseState to free all Lua-managed memory.
| Function | Description |
| NewState() | Create a new Lua interpreter with all standard libraries pre-loaded |
| NewBareState() | Create a minimal state with no libraries; add only what you need |
| CloseState(L) | Destroy the interpreter and free every byte of associated memory |
| OpenLibs(L) | Open all standard libraries (io, os, math, string, table, package, coroutine, …) |
| OpenSafeLibs(L) | Open only safe libraries (math, string, table) — excludes io and os |
Execute
Run Lua code strings or files and collect their output or return values.
| Function | Description |
| ExecString(L, Code) | Run a Lua script string. Returns '' on success or the error message. |
| ExecFile(L, Path) | Run a Lua script file by path. Returns '' on success or the error message. |
| EvalString(L, Code) | Execute Lua code and return the result as a string. |
| EvalNumber(L, Expr) | Evaluate a Lua expression and return the result as a Double. |
| EvalBool(L, Expr) | Evaluate a Lua expression and return the result as a Boolean. |
Call Functions
Call named global functions defined in Lua from your PascalAI code.
| Function | Description |
| CallFunc(L, FuncName, Args) | Call a global Lua function with an array of string arguments; returns string result. |
| CallFuncNoArgs(L, FuncName) | Call a global Lua function with no arguments; returns string result. |
| FuncExists(L, FuncName) | Returns True if the named global function exists in the state. |
Global Variables
Exchange typed values between PascalAI and Lua via the global environment.
| Function | Description |
| SetGlobalString(L, Name, Value) | Set a global string variable in Lua |
| SetGlobalNumber(L, Name, Value) | Set a global float64 variable |
| SetGlobalInt(L, Name, Value) | Set a global int64 variable |
| SetGlobalBool(L, Name, Value) | Set a global boolean variable |
| GetGlobalString(L, Name) | Read a global string variable from Lua |
| GetGlobalNumber(L, Name) | Read a global float64 variable |
| GetGlobalInt(L, Name) | Read a global int64 variable |
| GetGlobalBool(L, Name) | Read a global boolean variable |
| GetGlobalType(L, Name) | Return the TLuaType of any global variable |
Table Access
Read and write fields in Lua tables and query table structure from PascalAI.
| Function | Description |
| GetTableString(L, Table, Field) | Read tbl.field as a string from a global table |
| SetTableString(L, Table, Field, Value) | Write tbl.field = value into a global table |
| TableLength(L, Table) | Return the sequence length of a table (Lua # operator) |
| TableKeys(L, Table) | Return all keys of a global table as an array of strings |
Register C Functions
Expose PascalAI/host functions into Lua so that Lua scripts can call back into your application.
| Function | Description |
| RegisterFunc(L, Name) | Register the named host function as a Lua global callable from scripts |
Tip — host callbacks
Use RegisterFunc to expose logging, HTTP calls, or database queries to Lua scripts without giving them unrestricted system access.
Sandbox
Run untrusted Lua code safely by combining a bare state with restricted libraries and resource limits. Two independent limits are available: instruction count (CPU) and memory.
| Function | Description |
| SetInstructionLimit(L, Count) | Raise an error if the script executes more than Count VM instructions. Pass 0 for unlimited. |
| SetMemoryLimit(L, Bytes) | Raise an error if total Lua allocation exceeds Bytes. Pass 0 for unlimited. |
| RemoveGlobal(L, Name) | Set a global to nil, removing it from the script environment |
Instruction limit example
uses lua;
var L := NewBareState();
OpenSafeLibs(L);
{ Deny access to dangerous globals }
RemoveGlobal(L, 'dofile');
RemoveGlobal(L, 'loadfile');
RemoveGlobal(L, 'require');
{ Hard CPU cap: 500 000 instructions }
SetInstructionLimit(L, 500000);
var err := ExecString(L, userScript);
if err <> '' then
WriteLn('Script error: ' + err);
CloseState(L);
Memory limit example
uses lua;
var L := NewBareState();
OpenSafeLibs(L);
{ Allow at most 2 MB of Lua heap }
SetMemoryLimit(L, 2 * 1024 * 1024);
var err := ExecString(L, 'local t = {} for i=1,1e9 do t[i]=i end');
if err <> '' then
WriteLn('Caught: ' + err); { memory limit exceeded }
var used := MemoryUsed(L);
WriteLn('Heap used: ' + IntToStr(used) + ' bytes');
CloseState(L);
Garbage Collector
Control Lua's GC directly when you need deterministic collection or want to profile memory usage.
| Function | Description |
| GC(L, Mode, Arg) | Control the GC with a TLuaGCMode command (stop, restart, collect, step, set pause, set step multiplier, switch mode) |
| MemoryUsed(L) | Return the current Lua heap usage in bytes |
uses lua;
var L := NewState();
{ Switch to generational GC for short-lived allocations }
GC(L, lgcGen, 0);
{ ... run scripts ... }
{ Force a full collection }
GC(L, lgcCollect, 0);
WriteLn('Memory after GC: ' + IntToStr(MemoryUsed(L)) + ' bytes');
CloseState(L);
Info
| Function | Description |
| LuaVersion() | Return the Lua version string, e.g. "Lua 5.4.6" |