Lua ~ Research on the C API in Lua - uchicago-cs/chiventure GitHub Wiki

Research on the C API in Lua

Lua is a library that can be linked within C source code files through what is known as an application programming interface (API). This API is a set of functions that allow C code to interact within the Lua environment which is separate altogether. This includes the ability to use Lua global variables, access Lua functions, and also to allow for Lua code to interact with certain C functions.

Most importantly, however, the communication between Lua and C occurs on a virtual stack through which all calls and exchanges take place. This abstract stack can a number of different types of values including integer, string, and Boolean types. In other words, this means that variables in C must first be pushed onto this virtual stack before they can be accessed by Lua code and implemented by the Lua library.

Important Header Files

lua.h -- defines basic functions provided by Lua. lauxlib.h -- is an auxiliary library of lua.h that provides a higher level of abstraction. lualib.h – another library that allows for the API interactions between C and Lua to take place.

Structure of Lua

There is a dynamic structure called lua_State which holds all arguments to functions in Lua. Typically, a pointer to this structure is passed as an argument to all functions inside Lua.

Example Code Demonstrating this:

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. */

luaL_loadfile(L, filename) /* loads a file into Lua */

lua_pcall(L,0,0,0) /* Plays a very important role in Lua specifically to do with executing Lua functions by taking in a number of arguments from the lua_state */

Lua Push Functions – Between C and Lua, all data is stored on a virtual stack which requires that C source code pushes all types of data to the stack

void lua_pushnil (lua_State *L); -- Pushes a NULL value to the stack

void lua_pushboolean (lua_State *L, int bool); -- Pushes a boolean value to the stack

void lua_pushnumber (lua_State *L, double n); -- Pushes an integer value to the stack

void lua_pushstring (lua_State *L, const char *s); -- Pushes a string to the stack

int lua_checkstack (lua_State *L, int sz); -- Checks to see how much space is available on the stack

Functions to receive elements from Lua

int lua_toboolean (lua_State *L, int index);

double lua_tonumber (lua_State *L, int index);

const char* lua_tostring (lua_State *L, int index);

size_t lua_strlen (lua_State *L, int index);

Other Important Functions that allow for Exchange of Values in C

int lua_gettop (lua_State *L);

void lua_settop (lua_State *L, int index);

void lua_pushvalue (lua_State *L, int index);

void lua_remove (lua_State *L, int index);

void lua_insert (lua_State *L, int index);

void lua_replace (lua_State *L, int index);

Specific Data Types/Structures in C

To represent array values, Lua provides a basic type specifically for this: userdata. A userdatum offers a raw memory area with no predefined operations in Lua.

The Lua API offers the following function to create a userdatum:

void *lua_newuserdata (lua_State *L, size_t size);

Sending C Functions to Lua

Requires functions to have a specific type definition as follows:

typedef int (*lua_CFunction) (lua_State *L);

From the point of view of C, a C function gets as its single argument the Lua state and returns (in C) an integer with the number of values it is returning. In order for this function to be used by Lua, it must first be registered through the lua_pushcfunction as follows:

lua_pushcfunction( /* number of arguments /, / name of C function here */);

lua_setglobal(/*number of arguments */, "global_variable");

The C function can now be executed inside a Lua program after having been stored in a global variable.

Error Handling:

Unlike other languages Lua can be used with such as Java & C++, C does not have an exception handling mechanism. Lua thus used "setjmp" from C, which offers a similar facility. Since all structures are dynamic in Lua, meaning that they grow as needed, there is a chance of memory failure occuring. Instead of using error codes to signal an error, Lua uses exceptions to signal these errors. This means that API functions may throw an error instead of returning a value When we write library code (that is, C functions to be called from Lua), the use of long jumps is almost as convenient as a real exception-handling facility, because Lua catches any occasional error. When we write application code (that is, C code that calls Lua), however, we must provide a way to catch those errors.

Source: https://www.lua.org/pil/24.1.html (LUA Website for the C API)