Lua stacks in C

Retrospective

In this post we looked a little bit at how Lua uses stacks for a lot of things internally. Now we can look at how we need to explicitely work with the stacks in C when implementing a Lua interface.

The almighty Lua state

When combining C code with Lua there’s exactly one essential piece of information passed from call to call: The Lua state. It is once created and then updated to reflect the current state, you probbaly guessed it: it’s a stack; there’re ways to split the state and of course one can have several states at the same time but in essence there’s supposed to be exactly one and a linear usage.

Doing Lua the hard way: in C

No matter whether you’re implementing functions in C supposed to be called from Lua or calling Lua functions from C, the principle is always the same:

The calling signature always looks the same:

int func (lua_State *L)
{
}

The lua_State contains the stack mentioned above, (when called from Lua) adjusted to only have the passed arguments available on the stack. Now we come back to the basic three operations which can be applied to the stack:

It is good practise to balance the stack (in case you want to call other functions yourself so there’s always the expected number of elements on the stack). This means you should remove any temporary values you created in the function itself.

Then you do the processing and put the result on the stack and return the function with the number of result parameters on the stack.

Let’s have an example:

int minus (lua_State *L)
{
        int a = luaL_checknumber (L, 1);
        int b = luaL_checknumber (L, 2);
        int c = a - b;
        lua_pushnumber (L, c);
        return 1;
}

So int a = luaL_checknumber (L, 1); checks whether parameter 1 (from the bottom of the stack) can be expressed as an integer value and assigns it to the local variable a or it will create and error and return from the function if there was no argument or it evaluates to an incompatible type.

int b = luaL_checknumber (L, 2); does the same with parameter 2 and assigns it to the local variable b.

luaL_checknumber is a peek operation and will not modify the stack.

Note: Any excess parameter will simply be ignored.

int c = a - b; computes the result of a - b and stores it in c.

lua_pushnumber (L, c); takes the result and creates a new value of type number with it on the stack.

return 1; tells the Lua interpreter that there’s one result value to be kept by the stack; any additional values will automatically be removed but only if it is called via the Lua interpreter, otherwise (e.g. if functions call one another) the values will prevail.

Now we’ve seen peek and push operations in action, pop operations are usually used in conjuction with operations which pop values on the stack that need to be gotten rid off. An example would be you creating a new array which is supposed to be returned but then some error occurs so you want to get rid of the array (for symmetry reasons). Or you might be processing an array which will requires to have an index on the stack but will actually put the index and the value on the stack, so the latter will need to be popped of for the next iteration.

In closing

Today we’ve seen how to write a Luaish C function which could be called from Lua or another Luaish C function and the basic stack handling in C. The next posts will contain specific recipes for C lua bindings I had to figure out the hard way.

Until then, take care.