Skip to content

The LuaTable Object

David Siaw edited this page Mar 7, 2015 · 8 revisions

Tables are the only product type of Lua. What this means is that if you ever wanted to have an object that was a collection of information such as arrays, records, linked lists, trees, complex numbers, coordinates in 3D space, you could only use a table to describe that.

But since you want to use Lua you already knew that anyway. So let's go back to the configuration file loading program that we talked about earlier:

#include <fstream>
#include <streambuf>
#include <string>
#include <iostream>
#include <luacppinterface.h>

int main()
{
  std::ifstream file("config.lua");
  std::string script((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
  Lua lua;
  lua.RunScript(script);
  int width = lua.GetGlobalEnvironment().Get<int>("width");    // get the width
  int height = lua.GetGlobalEnvironment().Get<int>("height");  // get the height
  std::string windowTitle = lua.GetGlobalEnvironment().Get<std::string>("windowTitle");
  return 0;
}

The lua.GetGlobalEnvironment() call returns a LuaTable object. In Lua there are two tables that always have to exist. The Global Table and the Registry Table. Metatables also exist for all Lua objects, even integers and strings.

#Getting and Setting fields

You can do a bunch of things with a LuaTable object. The most basic methods on a LuaTable object are to Get and Set fields in the table as shown here:

Lua lua;
LuaTable global = lua.GetGlobalEnvironment();
global.Set("programVersion", 5);
global.Set("programAuthor", "The Little Prince");

This is equivalent to running a lua script that goes:

programVersion = 5
programAuthor = "The Little Prince"

You can only actually set and get keys that are Integers and Strings. This was a conscious design decision that I made on the reasoning that other kinds of keys (tables, functions, coroutines, user data) simply do not make sense to be keys in a record. I mean, how often do you need to go:

x = {}
x[{ field="lol", meow="woof" }] = 6
x[function (parameter)
  return parameter .. " is cool" 
end] = "coolness"

sure you can do it, BUT IT MAKES NO SENSE AT ALL! WHY THE HELL DO YOU WANT TO DO THAT TO YOURSELF!?

Hence, only int and string can be used as keys in C++ and NOTHING ELSE. You are of course, free to do whatever you want in Lua.

##BUT

While keys can only be integers and strings, values can be any of the types in the list of Primitive Types, which is actually a bunch of types that LuaCppInterface can and will marshal back and forth for you.

This means you can do this:

LuaTable setBunchOfThings(LuaTable table)
{
  table.Set("programVersion", 5);
  table.Set("programAuthor", "The Little Prince");
  table.Set(5, "Five");
  int number = table.Get<int>("aNumber");
  LuaTable anotherTable = table.Get<LuaTable>("anotherTable");
  return anotherTable;
}

Notice that you don't have to pass type parameters for Set but you need to for Get, this is because C++11 is awesome and can infer the type of value that you want to set on the table by simply looking at the value. However, it isn't quite smart enough to know that you are expecting an integer from the left side of the assignment operator, so you need to give it the hint.

Notice also that you can pass the LuaTable around just like that. Passing it around merely passes the LuaTable reference around. Nothing gets copied except the reference and the lua state.

** WAIT WHAT **

Yes, I said the Lua state. Even if you destroy your Lua state, even if you delete it, all Lua objects that originate from this Lua state will keep the Lua state alive until everyone is dead. If you want to know more have a look at the documentation about the LuaReference Object

#Creating a LuaTable

So how do you create a new LuaTable?

Easy:

LuaTable table = lua.CreateTable();

What, did you expect more?

In summary, the code:

Lua lua;
LuaTable global = lua.GetGlobalEnvironment();
global.Set("aNewTable", lua.CreateTable());

is equivalent to

aNewTable = {}

#Getting The Value Type

You can use this function to find the type of the value at a particular key. This is useful if you aren't sure whether its a string or not. Using this, you can also find out if a key exists or not.

LuaType::Value type = table.GetTypeOfValueAt("name");

The return value of GetTypeOfValueAt() is one of the enums described in LuaType.h

If you get LuaType::None, it means the member is not set.

#Iterating through the fields

Alright, so now someone gives you a lua array (we know lua arrays are just lua tables with fields keyed on a number which is their index), or a lua table, and we need to go through each of the things in the array. Here's how:

void printAllKeys(LuaTable table)
{
  table.ForAllStringKeys([](std::string name, LuaType::Value valueType)
  {
    std::cout << name << std::endl;
  }

  table.ForAllIntegerKeys([](int index, LuaType::Value valueType)
  {
    std::cout << index << std::endl;
  }
}

Remember, only string and integer keys.

Now that we know a lot about the LuaTable object, we realize that functions with no side effects are actually generalizations of a key-value table. Next we should take a look at Lua functions and how to use LuaCppInterface's very powerful template system to make, interact with, provide functions to and get functions from a Lua script.

Next: The LuaFunction object

Clone this wiki locally