Compatibility With Lua Five

lua-users home

This page provides some hints developers can adopt to transform code written to Lua 5.1 compatible with also Lua 5.0 and Lua 5.2.

The main goal of this page is the same as [Compat5-1], but the form is a set of hints rather than a set of files.

There is a [Compatibility module providing Lua-5.2-style APIs for Lua 5.1] made by Hisham.


(Between parenthesis there is an indication of what target Lua version the change is aimed to)

Lua files

Standardize calls to require() (Lua 5.0 and 5.1)

Rewrite calls to require to save its return value (see also "module()" below). For example:


Turns into

local lib = require"lib"


Remove module() (Lua 5.1)

Calls to module() can be removed and the code should be adapted to return a table containing the exported functions. There are different ways to adapt the code. The simpler is:

local function func1(...) ... end
local function func2(...) ... end

return {
    func1 = func1,
    func2 = func2,

Some modules could need another approach such as:

local _M = {}
function _M.func1(...) ... end
function _M.func2(...) ... end

return _M


environments (Lua 5.1)

The changes related to environments from Lua 5.0 to Lua 5.2 are tricky and should be corrected manually.

Remove calls to table.getn() (Lua 5.0)

table.getn is defined only in Lua 5.0 and the length operator is recommended substitution for it on the following versions (see a [note on the deprecation of table.getn]).

If table.getn is used only in test files, it can be defined:

if string.find(_VERSION, " 5.0") then
    table.getn = function (t)
        if t.n then
            return t.n
            local n = 0
            for i in pairs(t) do
                if type(i) == "number" then
                    n = math.max(n, i)
        return n

Although the distribution of separate files for the different versions of Lua should be considered in this case.

removing old for construction (Lua 5.0)

The old construction should be easily transformed to a Lua 5.X compatible form:

for i,v in t do ... end

Should be rewritten to:

for i,v in pairs(t) do ... end


scope of variables in for and repeat (Lua 5.0)

There was a change in the scope of the implicit for variable and local variables in repeat from Lua 5.0 to Lua 5.1. This has to be checked manually.


nesting of long strings (Lua 5.0)

There is no way to write nesting long strings compatible to all Lua 5.X versions. The code should be adapted manually to avoid these constructions.

C files

Pushing integer numbers (Lua 5.0)

Since Lua 5.1, the function lua_pushinteger is defined. Despite being a function, the following macro will make Lua 5.1/5.2 code backwards compatible to Lua 5.0:

#if !defined(LUA_VERSION_NUM)
#define lua_pushinteger(L, n) lua_pushnumber(L, (lua_Number)n)

Defining a list of CFunctions (Lua 5.0)

luaL_reg (Lua 5.0) changed its name to luaL_Reg since Lua 5.1. This could be solved with conditional compilation:

#if !defined LUA_VERSION_NUM
/* Lua 5.0 */
#define luaL_Reg luaL_reg

Setting table fields (Lua 5.0)

Since Lua 5.1, the function lua_setfield is defined. Thus, the following macro could be defined to make Lua 5.1/5.2 code backwards compatible to Lua 5.0:

#if !defined(LUA_VERSION_NUM)
#define lua_setfield(L, i, k)   (lua_pushstring(L, k), lua_settable(L, i))

References (Lua 5.0 and Lua 5.1)

The deprecated functions lua_getref() and lua_unref() are easily transformed into a compatible call. For example:

/* This code is compatible with previous versions (4.0) */
lua_getref(L, ref);
lua_unref(L, ref);

Should be rewritten to:

/* This is Lua 5.X code *;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
luaL_unref(L, LUA_REGISTRYINDEX, ref);

Registering CFunctions (Lua 5.0 and 5.1)

Lua 5.2 modules are easily compatible with previous Lua 5.X versions provided a single function: luaL_setfuncs

#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501
** Adapted from Lua 5.2.0
static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
  luaL_checkstack(L, nup+1, "too many upvalues");
  for (; l->name != NULL; l++) {  /* fill the table with given functions */
    int i;
    lua_pushstring(L, l->name);
    for (i = 0; i < nup; i++)  /* copy upvalues to the top */
      lua_pushvalue(L, -(nup+1));
    lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
    lua_settable(L, -(nup + 3));
  lua_pop(L, nup);  /* remove upvalues */

Also, calls to luaL_openlib() and to luaL_register() should be changed according to its second argument.

Calls such as luaL_openlib(L, NULL, lreg, x); should be rewritten to luaL_setfuncs(L, lreg, x);.

Calls such as luaL_openlib(L, name, lreg, x); should be carefully rewritten because a global table with the given name will be searched and possibly created.

Calls such as luaL_register(L, NULL, lreg); should be rewritten to luaL_setfuncs(L, lreg, 0);.

Calls such as luaL_register(L, name, lreg); should be carefully rewritten because a global table with the given name will be searched and possibly created. When possible, it should be rewritten to luaL_setfuncs(L, lreg, 0);

RecentChanges · preferences
edit · history
Last edited February 7, 2014 5:30 pm GMT (diff)