lua clib Scripting / Embed

Lua 5.4 scripting engine. Embed Lua in your app: execute scripts, call functions, exchange values, sandboxed eval.

ppm install lua

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

PropertyDetail
Size~300 KB compiled library — smallest production-grade scripting engine
SpeedFastest interpreted language in most benchmarks; register-based VM
MemoryPrecise GC with both incremental and generational modes
CoroutinesNative cooperative multitasking via coroutine.*
TablesUniversal data structure: arrays, maps, objects, modules — all one type
MetatablesOperator overloading, OOP, custom metamethods without special syntax
C APISimple stack-based interface; register any host function callable from Lua

Lua 5.4 Features

FeatureDescription
Integer typeSeparate int64 and float64 types; integer arithmetic no longer goes through float
Generational GCNew 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

ProjectHow Lua is used
RedisServer-side scripting with EVAL — millions of scripts run daily
nginx / OpenRestyFull web application framework built on top of embedded Lua
World of WarcraftAll UI addons and game logic written in Lua
FactorioEntire game modding API; mods are plain Lua scripts
WiresharkProtocol dissectors and post-analysis scripts
VLCExtensions, interface scripts, playlist parsers
NmapNSE (Nmap Scripting Engine) for port and service detection
Adobe LightroomPlugin API and automation scripts
LOVE2DFull 2D game framework where every game is a Lua program

Comparison

vs.Verdict
PythonLua 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
WrenLua 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

TypeDescription
TLuaStateHandle to a Lua interpreter instance. All API calls take this as the first argument.
TLuaTypeEnumeration of Lua value types returned by GetGlobalType.
TLuaGCModeGarbage 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.

FunctionDescription
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.

FunctionDescription
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.

FunctionDescription
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.

FunctionDescription
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.

FunctionDescription
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.

FunctionDescription
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.

FunctionDescription
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.

FunctionDescription
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

FunctionDescription
LuaVersion()Return the Lua version string, e.g. "Lua 5.4.6"

Package Info

Version1.0.0
Typeclib
C Libraryliblua5.4-dev
Authorgustavo

System Requirements

liblua5.4-dev

Ubuntu/Debian:
sudo apt install liblua5.4-dev

TLuaType Values

ltNone — -1 (not present)
ltNil — 0
ltBoolean — 1
ltLightUserData — 2
ltNumber — 3
ltString — 4
ltTable — 5
ltFunction — 6
ltUserData — 7
ltThread — 8 (coroutine)

Functions

  • NewState / NewBareState
  • CloseState
  • OpenLibs / OpenSafeLibs
  • ExecString / ExecFile
  • EvalString / EvalNumber
  • EvalBool
  • CallFunc / CallFuncNoArgs
  • FuncExists
  • SetGlobalString / GetGlobalString
  • SetGlobalNumber / GetGlobalNumber
  • SetGlobalInt / GetGlobalInt
  • SetGlobalBool / GetGlobalBool
  • GetGlobalType
  • GetTableString / SetTableString
  • TableLength / TableKeys
  • RegisterFunc
  • SetInstructionLimit
  • SetMemoryLimit
  • RemoveGlobal
  • GC / MemoryUsed
  • LuaVersion