14-07-2021

Lua is an extremely powerful interpreted language. It is most well known for its use in API’s (Application Programming Interface). From World of Warcraft to Kaseya’s VSA, all sorts of applications in different industries rely on Lua to make things work. Lua is almost everywhere, but is still relatively unknown.

Import your existing (C, C, Java or Obj-C) code, bind to Lua and interpret them directly. Dozens of open-source plugins are already developed and ready to use. Clean OOP approach − Gideros provides its own class system with all the basic OOP standards, enabling you to write clean and reusable code for any of your future games. The Lua programming language is the most widely used scripting language in games. It’s implemented internally as a very compact register-based bytecode VM. Kismet is a graphical scripting tool built into UnrealEd, the editor for the Unreal engine. For this the game would need to be scriptable. Also I don't aim to commercialize it, it is merely an interesting programming challenge for me. As I am mostly a.NET guy I will use XNA/C# for the game itself. For the scripting I think about going with Python or Lua. I have previous experience with Python and have nothing against it as a language.

Lua is more than just a language for API’s, it excels as a programming language in its own right. It’s fast and efficient, especially considered to other interpreted languages. Lua also has a JIT (Just In Time) compiler which makes it even faster for certain applications.

You can use it for making games, it has many modern frameworks which keep it competitive, and it’s great for general purpose system scripting. Lua is a powerhouse when used correctly. I’ve used it to replace Perl for most tasks and for Windows automation.

Lua For Games

Frameworks like Love2D (or LÖVE) and Corona make Lua practical for game programming. These two frameworks allow the creation of professional games which are cross-platform. Both are extremely mature and feature-rich.

LÖVE allows you to implement 2D games easily and efficiently from the ground up with worrying about the low-level graphics. The engine is extremely powerful and intuitive. It also has many extra libraries to add things like collision detection and similar. LÖVE’s only fallback is a lot of the library names can sound a bit immature.

Lua Vs C Game Scripting

Corona is a library for building games for the likes of iOS and Android as well as more traditional environments like Windows and MacOS. It’s free and open-source. Corona also has a massive community backing it and making it easy to learn and work with. It also works with Steam’s platform with a plugin.

Corona is the more commercially viable of the two for sure, but LÖVE is a great framework to learn on and to work with. There are still games on which are made with LÖVE, but they require extra work to get there. Both of these frameworks are extremely powerful and feature rich and can be used to make high quality games relatively easily.

Modern App Frameworks

If you don’t care about making games, Lua still has you covered. Lua has modern web frameworks via Lapis and Luvit (among many). It also has a deep machine learning framework via Torch. All of these are open source and easy to use (all things considered).

Lapis allows the creation of flexible, self-contained REST API based applications (brush up on your JSON). With a little extra work, you can use it for quick, self-contained microservices. It can easily be extended to resemble Perl’s Dancer and many other equivalent frameworks.

If Node.JS is more your thing, give Luvit a chance. Luvit implements the same API as Node.JS in Lua so it’s easy to migrate to or use if you’re already used to Node. It’s mature, extensible, and uses a similar backing as one of the most popular asynchronous frameworks in the world.

Aside from Lapis and Luvit, there are dozens of other frameworks of varying levels of maturity with different philosophies. I never really felt the need to move from Lapis for anything I do with web programming in Lua so I haven’t played with all that many. That being said, there are a lot.

Torch is an extremely powerful scientific framework for LuaJIT which is often used for machine learning. Torch works well with C, leverages GPU’s, and is extremely flexible. For a machine learning framework, it is extremely simple but powerful. For instance, it can be used for deep machine learning as easily (from a technical side) as any other algorithm of choice. There is also an extremely strong community around Torch.

General Purpose Scripting

Lua is extremely powerful as a general purpose scripting language. I have used it extensively for scripting in a systems admin position due to how small the binaries are and how efficient it is. You don’t need to worry about versioning (unlike with Powershell) when you’re dropping precompiled binaries on each machine. The compressed 7Z package for my entire drop tends to be less than a single megabyte. You don’t have to do much to make a script work on different Windows versions from 2000 to present, and it’s built into most Linux distributions.

Scripting

Lua features regular expressions and is Unicode agnostic. It has OS level libraries, can handle files, and basically any task a standard language can do. I feel the need to clarify this as most people who have worked with or heard about Lua only know it as an “API language” rather than a standalone language.

It has tables, classes, logic, and all of the other basics, as well as bells and whistles you’d expect from a modern programming language. The core language is extremely simple, but it’s simple like C. The language can be extended with packages via LuaRocks or similar depending on the platform.

Using Lua

Lua can do so much more than just extend applications. There are mature frameworks for basically any task you can think of. The language is simple but rich, terse but relaxed, and flexible but powerful. You don’t need to compile anything, but you can if you want with LuaJIT.

See why Lua is so much more than that API language for Roblox. Give it a try and see just why it is good for making games, or applications. Automate your worries away with a powerful, flexible language which is also quick to scaffold and implement with. You won’t even need to worry about how to build an API into your application!

Image by Free-Photos from Pixabay

  • Initial Examples
  • More examples

Introduction

Allowing users to extend your apps with scripts it is an amazing feature. There are many languages for this purpose, but Lua is the choice today, it is powerful and easy to embed.

Lua is an important tool for many industries, it has been used inside Game Engines, Databases like Redis, and HTTP servers like Nginx, powering users to extend their features.

I will show you some essential but complete examples in how to work with Lua, I will not cover some deep concepts behind the language, installation and other topics like LuaJIT.

Another thing that I will not cover is how to compile and link your app with Lua library, if you know a little about C you can do it with almost no effort using the official manual, the goal here is talking about examples and how to use the API. But if you do not know how to do, check my repository link with examples at the end of this article.

Installation

How I said I do not cover the installation of Lua development libraries, because it varies and depends on your platform.You can look at the installation guide in the official website here.

Some Lua Concepts

It is important you understand at least one concept before, the virtual stack. Lua uses a virtual stack to pass values to and from C.

All communication between lua code and your application works using the virtual stack. You push data from C for defining global variables, tables, functions and function arguments. Lua VM will be made all this data available inside Lua script. When a Lua code calls a C function, for example, inside the function you have to recover the arguments and push the result again to Lua.

Another example is when you need to call from C a Lua function. You have to call an API function to let Lua knows which function should be put onto the stack to be available to C call it.

Now you are ready to start coding.

Starting Lua VM

The basic code that we need to call when we use Lua C API is as follow. We start declaring a lua_State pointer and initialize it with luaL_newstate() function.

Note that versions before 5.3 lua_open() is used instead.

It is our pointer to our Lua Virtual Machine and this lua_State store all data that we share between Lua and C. We can have many Lua states to run scripts with different contexts.

After opening a state, we are ready to call functions from Lua API.

One important function to be called is luaL_openlibs, it makes available the Lua Standard Library for the code that we will run afterwards. It is not a requirement, but without this you will not be able to call functions from libraries like math, io, string, utf8, inside Lua code.

You can also open only the libraries that you know it will be useful or safe to allow scripts to call, see the example bellow, more information here.

After using the lua state, when you do not need to execute anything else, you have to close the state with:

Initial Examples

I wrote some examples of basic operations like running Lua code from a string, loading a script file, exposing variables and C functions to Lua code, recovering the values from global variables inside the Lua code and calling Lua function in C.

Initializing Lua VM

Here is our first example, it is a starting point for using Lua with C.

Let's dissect the code structure. We start adding the headers:

Lua scripting tutorials

Start a new Lua state:

With L state your now able to call Lua C API.

Open the Lua standard libraries, like math, string, utf8, io, etc.:

After using Lua we need to close the state:

Running Lua code

This example shows how to load a Lua code from string and run it.

The new things here are the API functions: luaL_loadstring, that is in charge of loading the code chunk on the top of the stack, lua_pcall is in charge of running the code in the stack, and if the execution is successfull, we remove the code from the top(lua_gettop) of the stack with lua_pop.

More examples

Before continuing the examples I have to explain some updates made in the article.

After the feedback that I received, I decided to make the following examples more clear and simple using some macros available from Lua API.

The following changes were made:

  • Instead of using lua_pcall, luaL_loadstring, and luaL_loadfile, I modified the code to use:
    • luaL_dostring, which is equivalent to calling lua_pcall and luaL_loadstring
    • luaL_dofile, which is equivalent to calling lua_pcall and luaL_loadfile
    • use lua_pcall only when I do not run the function just after loading a file or a string.

All those macros use LUA_MULRET, which is an argument that tells lua_pcall that it must expect a variable number of returned values.

Another point is that when we call lua_pcall or its variants, a result is returned indicating if the call was successfully executed or not. We can use the constant LUA_OK to check if there is a success or not. When an error happens during lua_pcall, it returns a different value of LUA_OK and puts the error on the top of the stack. We are able to get this error using lua_tostring(L, lua_gettop(L)).

In this article I do not use lua_call because it is a non-protected way to call a function, its use implies that Lua will call a panic function and then call abort. It is possible to handle those errors settings a new panic function with lua_atpanic, but it is not covered in this article.

Using the protected call, any error will make Lua call longjmp, recover from the most recent active recovery point and set the error on top of stack.

Exposing a Simple Variable

It is really common to need to expose some variables for Lua code, and it is simple to do this:

We use here lua_pushinteger to put an integer on the top of the stack and after it, we use lua_setglobal to get this value and set as a global variable named as answer.

Lua Vs C Game Scripting Simulator

After exposing the variable we can use it inside the Lua code.

Note: For more complex types and structures, check Lua manual.

Exposing a Single Function to Lua

This example is a little bit more complex, I added some comments inside the code to explain the more important lines.

This example is similar to the exposing variables, but here we push a function pointer instead of an integer value.

Exposing Functions to Lua with Namespace

We use a table to create a namespace, we put all functions inside this table.

Running a Lua Script

The only difference between running code from string or file it is that we use luaL_loadfile instead of luaL_loadstring.

Getting a Global Variable from Lua

Retrieving values from a Lua script it is a good way of configuring your app.

Note that we can only get the variable after running the Lua code.

Calling a Lua Function in C

Calling a function defined in a Lua code it is pretty similar of getting a variable, but to execute the function you must check if it is a function on the top of the stack with lua_isfunction and call it with lua_pcall. If it is successfully executed you have to remove from the stack with lua_pop(l, lua_gettop(l)).

Calling a Lua Function in C with Arguments and Return Value

When you call a function defined in Lua, you can pass arguments values and get the return value. To do that you need put onto the stack the list of arguments after putting the function on the stack. After running the function you can check on the top of the stack a get the return value.

Example of Error Handling

A simple way to handle errors when calling a function:

The End

There is much more about this topic, you can learn more about Lua in the official manual, LuaJIT is another important topic, that it is a way to use Lua with a better performance. If you are interested in game development, check Love2D that is an amazing tool. Finally, check my repository with all examples. I hope it will be useful for you.

Thank you!

Lua Game Script

Extra Resources