This first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences.
The fourth edition targets Lua 5.3 and is available at Amazon and other bookstores.
By buying the book, you also help to support the Lua project.


24.1 – A First Example

We will start this overview with a simple example of an application program: a stand-alone Lua interpreter. We can write a primitive stand-alone interpreter as follows:

WARNING: this code is for Lua 5.0. To run it in Lua 5.1, you must change the five calls luaopen_*(L) to a single call to luaL_openlibs(L).

    #include <stdio.h>
    #include <string.h>
    #include <lua.h>
    #include <lauxlib.h>
    #include <lualib.h>
    
    int main (void) {
      char buff[256];
      int error;
      lua_State *L = lua_open();   /* opens Lua */
      luaopen_base(L);             /* opens the basic library */
      luaopen_table(L);            /* opens the table library */
      luaopen_io(L);               /* opens the I/O library */
      luaopen_string(L);           /* opens the string lib. */
      luaopen_math(L);             /* opens the math lib. */
    
      while (fgets(buff, sizeof(buff), stdin) != NULL) {
        error = luaL_loadbuffer(L, buff, strlen(buff), "line") ||
                lua_pcall(L, 0, 0, 0);
        if (error) {
          fprintf(stderr, "%s", lua_tostring(L, -1));
          lua_pop(L, 1);  /* pop error message from the stack */
        }
      }
    
      lua_close(L);
      return 0;
    }
The header file lua.h defines the basic functions provided by Lua. That includes functions to create a new Lua environment (such as lua_open), to invoke Lua functions (such as lua_pcall), to read and write global variables in the Lua environment, to register new functions to be called by Lua, and so on. Everything defined in lua.h has the lua_ prefix.

The header file lauxlib.h defines the functions provided by the auxiliary library (auxlib). All its definitions start with luaL_ (e.g., luaL_loadbuffer). The auxiliary library uses the basic API provided by lua.h to provide a higher abstraction level; all Lua standard libraries use the auxlib. The basic API strives for economy and orthogonality, whereas auxlib strives for practicality for common tasks. Of course, it is very easy for your program to create other abstractions that it needs, too. Keep in mind that the auxlib has no access to the internals of Lua. It does its entire job through the official basic API.

The Lua library defines no global variables at all. It keeps all its state in the dynamic structure lua_State and a pointer to this structure is passed as an argument to all functions inside Lua. This implementation makes Lua reentrant and ready to be used in multithreaded code.

The lua_open function creates a new environment (or state). When lua_open creates a fresh environment, this environment contains no predefined functions, not even print. To keep Lua small, all standard libraries are provided as separate packages, so that you do not have to use them if you do not need to. The header file lualib.h defines functions to open the libraries. The call to luaopen_io, for instance, creates the io table and registers the I/O functions (io.read, io.write, etc.) inside it.

After creating a state and populating it with the standard libraries, it is time to interpret the user input. For each line the user enters, the program first calls luaL_loadbuffer to compile the code. If there are no errors, the call returns zero and pushes the resulting chunk on the stack. (Remember that we will discuss this "magic" stack in detail in the next section.) Then the program calls lua_pcall, which pops the chunk from the stack and runs it in protected mode. Like luaL_loadbuffer, lua_pcall returns zero if there are no errors. In case of errors, both functions push an error message on the stack; we get this message with lua_tostring and, after printing it, we remove it from the stack with lua_pop.

Notice that, in case of errors, this program simply prints the error message to the standard error stream. Real error handling can be quite complex in C and how to do it depends on the nature of your application. The Lua core never writes anything directly to any output stream; it signals errors by returning error codes and error messages. Each application can handle these signals in a way most appropriate for its needs. To simplify our discussions, we will assume for now a simple error handler like the following one, which prints an error message, closes the Lua state, and exits from the whole application:

    #include <stdarg.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    void error (lua_State *L, const char *fmt, ...) {
      va_list argp;
      va_start(argp, fmt);
      vfprintf(stderr, argp);
      va_end(argp);
      lua_close(L);
      exit(EXIT_FAILURE);
    }
Later we will discuss more about error handling in the application code.

Because you can compile Lua both as C and as C++ code, lua.h does not include this typical adjustment code that is present in several other C libraries:

    #ifdef __cplusplus
    extern "C" {
    #endif
       ...
    #ifdef __cplusplus
    }
    #endif
Therefore, if you have compiled Lua as C code (the most common case) and are using it in C++, you must include lua.h as follows:
    extern "C" {
    #include <lua.h>
    }
A common trick is to create a header file lua.hpp with the above code and to include this new file in your C++ programs.