Categories
FFI Bindings
  • Github CLI
  • SSH
  • HTTPS
Clone Repo

zig-luajit

Zig ⚑ language bindings for the LuaJIT C API. Use zig-luajit to run Lua scripts within a Zig application.

Ubuntu Regression Tests Badge Windows Regression Tests Badge GitHub License

About

The goal of the zig-luajit project is to provide the most idiomatic Zig language bindings for the LuaJIT C API and C API Auxilary Library. Additionally the zig-luajit project emphasizes safety by making liberal use of runtime safety checks in Debug and ReleaseSafe builds and provides full test coverage of the API.

Zig Version

The main branch targets recent builds of Zig’s master branch (last tested with Zig 0.14.0).

Installation & Usage

It is recommended that you install zig-luajit using zig fetch. This will add a luajit dependency to your build.zig.zon file.

zig fetch --save=luajit git+https://github.com/sackosoft/zig-luajit

Next, in order for your code to import zig-luajit, you’ll need to update your build.zig to do the following:

  1. get a reference the zig-luajit dependency.
  2. get a reference to the luajit module, which contains the core Zig language bindings for LuaJIT.
  3. add the module as an import to your executable or library.
// (1) Get a reference to the `zig fetch`'ed dependency
const luajit_dep = b.dependency("luajit", .{
    .target = target,
    .optimize = optimize,
});

// (2) Get a reference to the language bindings module.
const luajit = luajit_dep.module("luajit");

// Set up your library or executable
const lib = // ...
const exe = // ...

// (3) Add the module as an import to your executable or library.
my_exe.root_module.addImport("luajit", luajit);
my_lib.root_module.addImport("luajit", luajit);

Now the code in your library or exectable can import and use the LuaJIT Zig API!

const luajit = @import("luajit");
const Lua = luajit.Lua;

var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const lua = Lua.init(gpa.allocator());
defer lua.deinit();

lua.openBaseLib();
lua.doString(
    \\ print("Hello, world!")
);

Examples

Some examples are provided in examples/ to aid users in learning to use zig-luajit. These small self-contained applications should always be working, please create an issue if they do not work for you.

Language Binding Coverage Progress

APISupport
Lua C API (lua_*)πŸŽ‰ 100% coverage† (92/92)
Auxilary Library (luaL_*)🀩 100% coverage (48/48)
Debug API (lua_Debug)πŸ₯³ 100% coverage (12/12)
LuaJIT ExtensionsNo plans to implement.

†: Coroutine yield/resume is not yet part of the public zig-luajit Zig API, see #6.

Coverage and Compatibility

This section describes the current status of Zig language bindings (β€œthe Zig API”).

  • β˜‘οΈ Fully Supported: Test coverage and runtime safety checks enabled in Debug or ReleaseSafe builds.
  • βž– Internal: Used internally and intentionally hidden from the Zig API.
  • πŸ†– Superseded: Has no direct Zig equivalent, but the functionality is provided by a different part of the Zig API.
  • πŸ“’ Renamed: Renamed in a non-obvious way from the C API. Renaming is avoided but done in cases deemed required:
    1. to conform to Zig idioms or patterns, such as the init() / deinit() pattern.
    2. to avoid conflicts with Zig language keywords, such as the Zig error keyword.
    3. to show that the Zig API has slightly different behavior than the C API, such as using lua.setAllocator() instead of lua.setAllocF(); since the Zig API uses std.mem.Allocator instead of allocation functions.
    4. to improve the clarity, discoverability or consistency of the symbol in the overall API surface.

Core C API Coverage (lua_)

C Type DefinitionAvailable in zig-luajit
lua_Stateβ˜‘οΈ Lua
lua_Allocβž– Hidden, please use lua.setAllocator() and lua.getAllocator()
lua_CFunctionβ˜‘οΈ lua.CFunction
lua_Integerβ˜‘οΈ Lua.Integer
lua_Numberβ˜‘οΈ Lua.Number
lua_Readerβ˜‘οΈ std.io.AnyReader
lua_Writerβ˜‘οΈ std.io.AnyWriter
C API SymbolsAvailable in zig-luajit
lua_atpanicβ˜‘οΈ lua.atPanic()
lua_callβ˜‘οΈ lua.call()
lua_pcallβ˜‘οΈπŸ“’ lua.callProtected()
lua_cpcallβ˜‘οΈπŸ“’ lua.callProtectedC()
lua_checkstackβ˜‘οΈ lua.checkStack()
lua_closeβ˜‘οΈπŸ“’ lua.deinit()
lua_concatβ˜‘οΈ lua.concat()
lua_createtableβ˜‘οΈ lua.createTable()
lua_dumpβ˜‘οΈ lua.dump()
lua_equalβ˜‘οΈ lua.equal()
lua_errorβ˜‘οΈπŸ“’ lua.raiseError()
lua_gcβ˜‘οΈ lua.gc() + lua.gcIsRunning()
lua_getallocfβ˜‘οΈπŸ“’ lua.getAllocator()
lua_getfenvβ˜‘οΈπŸ“’ lua.getEnvironment()
lua_getfieldβ˜‘οΈ lua.getField()
lua_getglobalβ˜‘οΈ lua.getGlobal()
lua_getmetatableβ˜‘οΈ lua.getMetatable()
lua_gettableβ˜‘οΈ lua.getTable()
lua_gettopβ˜‘οΈ lua.getTop()
lua_insertβ˜‘οΈ lua.insert()
lua_isbooleanβ˜‘οΈ lua.isBoolean()
lua_iscfunctionβ˜‘οΈ lua.isCFunction()
lua_isfunctionβ˜‘οΈ lua.isFunction()
lua_islightuserdataβ˜‘οΈ lua.isLightUserdata()
lua_isnilβ˜‘οΈ lua.isNil()
lua_isnoneβ˜‘οΈ lua.isNone()
lua_isnoneornilβ˜‘οΈ lua.isNilOrNone()
lua_isnumberβ˜‘οΈ lua.isNumber()
lua_isstringβ˜‘οΈ lua.isString()
lua_istableβ˜‘οΈ lua.isTable()
lua_isthreadβ˜‘οΈ lua.isThread()
lua_isuserdataβ˜‘οΈ lua.isUserdata()
lua_lessthanβ˜‘οΈ lua.lessThan()
lua_loadβ˜‘οΈ lua.load()
lua_newstateβ˜‘οΈπŸ“’ Lua.init()
lua_newtableβ˜‘οΈ lua.newTable()
lua_newthreadβ˜‘οΈ lua.newThread()
lua_newuserdataβ˜‘οΈ lua.newUserdata()
lua_nextβ˜‘οΈ lua.next()
lua_objlenβ˜‘οΈπŸ“’ lua.getLength()
lua_popβ˜‘οΈ lua.pop()
lua_pushbooleanβ˜‘οΈ lua.pushBoolean()
lua_pushcclosureβ˜‘οΈ lua.pushCClosure()
lua_pushcfunctionβ˜‘οΈ lua.pushCFunction()
lua_pushfstringβ˜‘οΈ lua.pushFString()
lua_pushintegerβ˜‘οΈ lua.pushInteger()
lua_pushlightuserdataβ˜‘οΈ lua.pushLightUserdata()
lua_pushliteralπŸ†– please use lua.pushLString()
lua_pushlstringβ˜‘οΈ lua.pushLString()
lua_pushnilβ˜‘οΈ lua.pushNil()
lua_pushnumberβ˜‘οΈ lua.pushNumber()
lua_pushstringβ˜‘οΈ lua.pushString()
lua_pushthreadβ˜‘οΈ lua.pushThread()
lua_pushvalueβ˜‘οΈ lua.pushValue()
lua_pushvfstringπŸ†– please use lua.pushFString()
lua_rawequalβ˜‘οΈπŸ“’ lua.equalRaw()
lua_rawgetiβ˜‘οΈπŸ“’ lua.getTableIndexRaw()
lua_rawgetβ˜‘οΈπŸ“’ lua.getTableRaw()
lua_rawsetiβ˜‘οΈπŸ“’ lua.setTableIndexRaw()
lua_rawsetβ˜‘οΈπŸ“’ lua.setTableRaw()
lua_registerβ˜‘οΈπŸ“’ lua.registerFunction()
lua_removeβ˜‘οΈ lua.remove()
lua_replaceβ˜‘οΈ lua.replace()
lua_resumeβž– Hidden, see Issue #6
lua_setallocfβ˜‘οΈπŸ“’ lua.setAllocator()
lua_setfenvβ˜‘οΈπŸ“’ lua.setEnvironment()
lua_setfieldβ˜‘οΈ lua.setField()
lua_setglobalβ˜‘οΈ lua.setGlobal()
lua_setmetatableβ˜‘οΈ lua.setMetatable()
lua_settableβ˜‘οΈ lua.setTable()
lua_settopβ˜‘οΈ lua.setTop()
lua_statusβ˜‘οΈ lua.status()
lua_tobooleanβ˜‘οΈ lua.toBoolean()
lua_tocfunctionβ˜‘οΈ lua.toCFunction()
lua_tointegerβ˜‘οΈ lua.toInteger()
lua_tolstringβ˜‘οΈ lua.toLString()
lua_tonumberβ˜‘οΈ lua.toNumber()
lua_topointerβ˜‘οΈ lua.toPointer()
lua_tostringβ˜‘οΈ lua.toString()
lua_tothreadβ˜‘οΈ lua.toThread()
lua_touserdataβ˜‘οΈ lua.toUserdata()
lua_typeβ˜‘οΈπŸ“’ lua.getType()
lua_typenameβ˜‘οΈ lua.getTypeName()
lua_xmoveβ˜‘οΈ lua.xmove()
lua_yieldβž– Hidden, see Issue #6

Auxilary Library Coverage (luaL_)

C Type DefinitionAvailable in zig-luajit
luaL_Bufferβ˜‘οΈ Lua.Buffer
luaL_Regβ˜‘οΈ Lua.Reg and Lua.RegEnd
C API SymbolAvailable in zig-luajit
luaL_addcharβ˜‘οΈ buffer.addChar()
luaL_addsizeβ˜‘οΈ buffer.addSize()
luaL_addlstringβ˜‘οΈ buffer.addLString()
luaL_addstringβ˜‘οΈ buffer.addString()
luaL_addvalueβ˜‘οΈ buffer.addValue()
luaL_argcheckβ˜‘οΈπŸ“’ lua.checkArgument()
luaL_argerrorβ˜‘οΈπŸ“’ lua.raiseErrorArgument()
luaL_buffinitβ˜‘οΈπŸ“’ lua.initBuffer()
luaL_callmetaβ˜‘οΈ lua.callMeta()
luaL_checkanyβ˜‘οΈ lua.checkAny()
luaL_checkintegerβ˜‘οΈ lua.checkInteger()
luaL_checkintπŸ†– please use lua.checkInteger()
luaL_checklongπŸ†– please use lua.checkInteger()
luaL_checklstringβ˜‘οΈ lua.checkLString()
luaL_checknumberβ˜‘οΈ lua.checkNumber()
luaL_checkoptionβ˜‘οΈ lua.checkOption()
luaL_checkstackβ˜‘οΈπŸ“’ lua.checkStackOrError()
luaL_checkstringβ˜‘οΈ lua.checkString()
luaL_checktypeβ˜‘οΈ lua.checkType()
luaL_checkudataβ˜‘οΈ lua.checkUserdata()
luaL_dofileβ˜‘οΈ lua.doFile()
luaL_dostringβ˜‘οΈ lua.doString()
luaL_errorβ˜‘οΈπŸ“’ lua.raiseErrorFormat()
luaL_getmetafieldβ˜‘οΈ lua.getMetaField()
luaL_getmetatableβ˜‘οΈπŸ“’ lua.getMetatableRegistry()
luaL_gsubβ˜‘οΈ lua.gsub()
luaL_loadbufferβ˜‘οΈ lua.loadBuffer()
luaL_loadfileβ˜‘οΈ lua.loadFile()
luaL_loadstringβ˜‘οΈ lua.loadString()
luaL_newmetatableβ˜‘οΈ lua.newMetatable()
luaL_newstateπŸ†– please use Lua.init()
luaL_openlibsβ˜‘οΈ lua.openLibs()
luaL_optintegerβ˜‘οΈπŸ“’ lua.checkIntegerOptional()
luaL_optintπŸ†– please use lua.checkIntegerOptional()
luaL_optlongπŸ†– please use lua.checkIntegerOptional()
luaL_optlstringβ˜‘οΈπŸ“’ lua.checkLStringOptional()
luaL_optnumberβ˜‘οΈπŸ“’ lua.checkNumberOptional()
luaL_optstringβ˜‘οΈπŸ“’ lua.checkStringOptional()
luaL_prepbufferβ˜‘οΈ buffer.prepBuffer()
luaL_pushresultβ˜‘οΈ buffer.pushResult()
luaL_refβ˜‘οΈ lua.ref()
luaL_unrefβ˜‘οΈ lua.unref()
luaL_registerβ˜‘οΈπŸ“’ lua.registerLibrary()
luaL_typenameβ˜‘οΈ lua.getTypeNameAt()
luaL_typerrorβ˜‘οΈπŸ“’ lua.raiseErrorType()
luaL_whereβ˜‘οΈ lua.where()

Debug API Coverage (lua_Debug)

C Type DefinitionAvailable in zig-luajit
lua_Debugβ˜‘οΈ Lua.DebugInfo
lua_Hookβ˜‘οΈπŸ“’ Lua.HookFunction
C API SymbolAvailable in zig-luajit
lua_getinfoβ˜‘οΈ lua.getInfo()
lua_getstackβ˜‘οΈ lua.getStack()
lua_gethookcountβ˜‘οΈ lua.getHookCount()
lua_gethookmaskβ˜‘οΈ lua.getHookMask()
lua_gethookβ˜‘οΈ lua.getHook()
lua_sethookβ˜‘οΈ lua.setHook()
lua_getlocalβ˜‘οΈ lua.getLocal()
lua_setlocalβ˜‘οΈ lua.setLocal()
lua_getupvalueβ˜‘οΈ lua.getUpvalue()
lua_setupvalueβ˜‘οΈ lua.setUpvalue()

Additions to the API in zig-luajit

The following functions are added in zig-luajit and do not necessarily have a corresponding function or macro in the C API.

zig-luajit Extension FunctionDescription
lua.getInfoFunction()A simplified version of lua.getInfo() for inspecting functions, that has a more idiomatic Zig result type.
lua.toNumberStrict()Gets the value of a number on the stack, without doing type coersion (e.g. from string values).
lua.toIntegerStrict()Gets the value of an integer on the stack, without doing type coersion (e.g. from string values).
lua.toBooleanStrict()Gets the value of a boolean on the stack, without doing type coersion based on β€œtruthyness” of the value.
lua.openBaseLib()Opens the Base Lua standard library.
lua.openMathLib()Opens the Math Lua standard library.
lua.openStringLib()Opens the String Lua standard library.
lua.openTableLib()Opens the Table Lua standard library.
lua.openIOLib()Opens the IO Lua standard library.
lua.openOSLib()Opens the OS Lua standard library.
lua.openPackageLib()Opens the Package Lua standard library.
lua.openDebugLib()Opens the Debug Lua standard library.
lua.openBitLib()Opens the Bit LuaJIT standard library.
lua.openJITLib()Opens the JIT LuaJIT standard library.
lua.openFFILib()Opens the FFI LuaJIT standard library.
lua.openStringBufferLib()Opens the StringBuffer LuaJIT standard library.

Licensing

The zig-luajit Zig languge bindings are distributed under the terms of the AGPL-3.0 License. The terms of this license can be found in the LICENSE file.

This project depends on source code and other artifacts from third parties. Information about their respective licenses can be found in the COPYRIGHT file.

Credits

This project was inspired by natecraddock/ziglua which provides great functionality if you’re looking to use Lua runtimes other than LuaJIT!

About
Run Lua code in Zig apps! A package providing Zig language bindings to LuaJIT.
Owner
sackosoft (Organization)
Last Commit
2025-03-12
Latest Release
Latest Release Date
2025-03-12
Created
2025-01-14