ziglua/docs.md
2022-06-06 09:20:15 -06:00

4.3 KiB

ziglua Documentation

To avoid a duplication of efforts, ziglua does not contain full documentation on the Lua C API. Please refer to the Lua C API Documentation for full details.

This documentation provides

  • An overview of ziglua's structure
  • build.zig documentation
  • Safety considerations
  • API Differences
  • Example code

Moving from the C API to Zig

While efforts have been made to keep the ziglua API similar to the C API, many changes have been made including:

  • Renaming or omitting functions
  • Modifying parameters (names and types) and return values
  • Additional helper functions have been added

With this in mind, here are some general guidelines to help guide when moving from the C to Zig APIs

Build Documentation

When integrating ziglua into your projects, the following three statements are required:

  1. @import() the build.zig file
  2. addPackagePath the ziglua api
  3. ziglua.link() the library with your executable

Note that this must be done after setting the target and build mode, otherwise ziglua will not know that information.

const ziglua = @import("lib/ziglua/build.zig");

pub fn build(b: *Builder) void {
    ...
    exe.addPackagePath("ziglua", "lib/ziglua/src/ziglua.zig");
    ziglua.link(b, exe, .{});
}

There is currently one option that can be passed in the third argument to ziglua.link():

  • .use_apicheck: defaults to false. When true defines the macro LUA_USE_APICHECK in debug builds. See The C API docs for more information on this macro.

API Differences

The major differences between the C and Zig Lua APIs are described below. This includes identifier renaming and omissions.

lua_tostring and lua_tolstring

These functions have been combined into Lua.toString(). The function lua_tostring is a macro around lua_tolstring and does not return the length of the string.

The length of the returned string is almost always needed, so `Lua.toString() returns a zero-terminated Zig slice of the bytes with the correct length.

lua_tointegerx and lua_tonumberx

Both of these functions accept an isnum return parameter to indicate if the conversion to number was successful. In the Zig version, both functions return either the number, or an error indicating the conversion was unsuccessful, and the isnum parameter is omitted.

Examples

Here are more thorough examples that show off the ziglua bindings in context. All examples use previously documented build.zig setup.

Simple Lua Interpreter

This is borrowed from Programming In Lua 4th Edition

const std = @import("std");
const ziglua = @import("ziglua");

const Lua = ziglua.Lua;

pub fn main() anyerror!void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();
    defer _ = gpa.deinit();

    // Initialize The Lua vm and get a reference to the main thread
    var lua = try Lua.init(allocator);
    defer lua.deinit();

    // Open the standard libraries
    lua.openLibs();

    var stdin = std.io.getStdIn().reader();
    var stdout = std.io.getStdOut().writer();

    var buffer: [256]u8 = undefined;
    while (true) {
        _ = try stdout.write("> ");

        // Read a line of input
        const len = try stdin.read(&buffer);
        if (len == 0) break; // EOF
        if (len >= buffer.len - 1) {
            try stdout.print("error: line too long!\n", .{});
            continue;
        }

        // Ensure the buffer is null-terminated so the Lua API can read the length
        buffer[len] = 0;

        // Compile a line of Lua code
        lua.loadString(buffer[0..len :0]) catch {
            try stdout.print("{s}\n", .{lua.toString(-1)});
            lua.pop(1);
            continue;
        };

        // Execute a line of Lua code
        lua.pCall(0, 0, 0) catch {
            try stdout.print("{s}\n", .{lua.toString(-1)});
            lua.pop(1);
        };
    }
}

This shows a basic interpreter that reads a string from stdin. That string is parsed and compiled as Lua code and then executed.

Notice that the functions lua.loadString() and lua.pCall return errors that must be handled, here printing the error message that was placed on the stack.