[ADV] Lua Stacks – used with Plug-ins or C API

Google is your friend, this is the most common feeling, in a way it is as over the years, it is the source of all information. Maybe for me, growing up in a non-google era and relying on a printed compiled/collated sources then also called (User Manuals) that outlined a lot of things, Google has been very good but I would still rather a collation that has everything together with the relevant bits than the whole whiz-bang. So when I was looking up Lua stacks, there were two things that happened, I found nothing that helped me with what I wanted or the information was so much that I could not read it as I was interested in a specific portion of that information. If you are like me and would like to know about a specific topic and Google for more detailed information read on. If you are from those that would like a very detailed overview or think that there are enough articles on this topic, please by all means don’t bother yourself reading on.

Lua C API

What is Lua C API. Lua as you know is an easy to use scripting language but the source is written in C and implemented as a series of C functions. When working with Plug-ins, using Lua with a C program (embedding it) you would require to use these functions.

What do these functions look like? These are simple C functions like lua_pushinteger, lua_pushstring etc. These functions use two parameters, one is the lua_State and the other is the data that we push or pop. Where are these pushed? That would be a good question, the way lua works is with a stack, it is on this stack that the values are pushed onto or popped off from.

Stack

Some functions return values, but most of them do not and they only work with the stack. When we pass values to a lua function and would like to take those parameters in our code (using the C Api) there is no easy way to say, give me parameter1 and give me parameter2. Instead you need to get the values off the stack. Easy, before you can complete saying that, there is a slight complexity that sometimes can be daunting for a beginner. While the text you can Google states/describes this well, it is the understanding of that which is an issue.

You would see code that shows things like

 int num = lua_tointeger(L, -1);
 const char *str = lua_tostring(L, -2);
 lua_pushinteger(L, num+3);
 return 1;

There are a couple of things that a beginner would ask, while the code looks easy to understand, it is still complex and can be confusing. Some other code might push or pop a positive value, while some code uses negative numbers, so what do these all mean?

To understand the Lua stack better, it would be easier to understand it using the Lua string as an example.

String

Let’s look closer to how the string works. Let’s consider the code

local theString = "OneTwoThree"

Now when we try to get a substring from this string, to extract One from this, we would get that as

 print(string.sub(theString, 1, 3)) --> One

and then to get Three, we could use

print(string.sub(theString, 7, 11)) --> Three

However with Lua, we can also use negative index values to indicate accessing the string from the right than from the left. With a negative index value, we could use it as follows

print(string.sub(theString, -5)) --> Three

If you have understood this, then stacks are easy to understand as it is used in a similar manner. The stack can be accessed with a positive index going top to the bottom or by using a negative index going from the last element up to the first element.

Why not just positive indexes?

For detailed understanding of the theories behind why use both positive and negative index, I would recommend Google. Lua stacks are LIFO, Last in First Out, just like a stack of playing cards, the card you place on top of the stack is the card that you can pick up first. Therefore to be able to access the items non-sequentially we use the positive or the negative index.

Untitled

Every time a new items is added to the stack, the numbers change, so it is not fixed, plus it would be very bad technique to populate the stack with more than a couple of items at a time. The functions should add and clear up the stack with minimal items left on the stack.

Usage of the Stack

We turn our attention back to the first bit of code

 int num = lua_tointeger(L, -1);
 const char *str = lua_tostring(L, -2);
 lua_pushinteger(L, num+3);
 return 1;

Let us look at this code and it’s interaction with the stack.

int num = lua_tointeger(L, -1);

This gets a value off the stack that is at the last position i.e. the item that was last pushed onto the stack.

const char *str = lua_tostring(L, -2);

This will return a string value off the stack that is in the second last position, i.e. the item that was pushed onto the stack before the last item.

lua_pushinteger(L, num+3);

We add a value that is num+3 back to the stack. This shall create a new item on the stack with the value of num+3.

return 1;

This line tells the function that the function has a single return value, which the other program could pick up off the stack using a negative index value.

In Lua, the return values of a function can be used as the input parameters of the other, thereby after we return from a function (as in our example) the other function could use that as a parameter. In this example above, it would translate in Lua as

function(strParam, numParam)
 return numParam + 3
end

So chaining this with another function would look like

a = function(strParam, numParam)
 return num + 3
end
print(a("Hello", 5))     --> 8

Hope this explains or helps to understand the Lua stack a bit better. In the next part, we shall look at how the stack is used to access tables.

Social tagging: > > > > >

Comments are closed.