Compat-5.1
Lua 5.1 Package Compatibility for Lua 5.0

Introduction

The Package Compatibility (Compat-5.1) is a set of files which provides an implementation of the Lua 5.1 package model to be used with Lua 5.0. It can be used by developers of Lua and Lua/C packages as much as by users that want to use those packages.

According to the Lua 5.1 specification, a package is a collection of one or more modules distributed together. Each module lives in single file, which contains a single module.

Modules can be loaded in (at least) three forms:

  • pre-loaded - the module is loaded in the Lua state during C initialization code, like the standard libraries;
  • pre-linked - the module code is linked with the Lua executable, but must be loaded explicitly;
  • dynamically - the module code is found through a search in some path, and then linked and loaded.

The compat-5.1.lua file reimplements the function require following the Lua 5.1 behavior and adds the function module; it also defines the table package and its standard fields:
path, cpath, loaded and preload.

The use of Compat-5.1 can be separated in two scenarios, one for the module developer (using C or Lua) and one for the module user.

Module Developers use C and/or Lua to develop new modules to be used on production environments. A production environment is defined by some hosting application that uses Lua as an extension language. It can be a simple command line interpreter or a huge enterprise application that is modularized to achieve its purposes.

Compat-5.1 for Module Developers

For a C developer, the C source file implements the function luaL_module. This function can replace the original luaL_openlib function so that a C module can be required from Lua. Files compat-5.1.c and compat-5.1.h should be used by developers; these files are not required in a production environment.

A C module developer can directly call luaL_module, or include compat-5.1.h. Including this file will replace the definition of luaL_openlib by luaL_module so a call to luaL_openlib will achieve the desired result. luaL_module is defined in the compat-5.1 library.

A Lua module developer can simply use the module function to define a new module that will be ready to be required by a module user.

Compat-5.1 for Module Users

Once a module complies with Compat-5.1, it can be used through the require function in the same way as Lua 5.1 does, as long as the module is found on the correct place in the system. More details on the configuration are given below.

Configuration

Both Lua 5.0 and Compat-5.1 have to be properly configured in order to know where the modules should be loaded from. This configuration assumes two independent search paths on the system, one for binary modules and another for Lua modules.

The binary search path defines a sequence of directories and file name patterns that will be looked when trying to load a binary module. In the same way, the Lua module search path will be looked when trying to load a Lua module.

The file compat-5.1.lua should be installed in your LUA_PATH (package.path) and must be loaded by the application before any other library that follows the package model (libraries don't need to require Compat-5.1).

A simple way to do that for the standalone interpreter is to define the environment variable LUA_INIT as the absolute path to the file, preceeded by the character '@' (see the Lua 5.0 standalone interpreter documentation for more details).

Finally, the file compat-5.1.lua should be edited so that the default values for the variables package.path and package.cpath are correct for the target system. The variables values should follow the actual installation paths and library's name conventions for the target system (?.dll for Windows, [l]?.so for Unix etc). You can also define LUA_PATH and LUA_CPATH as environment variables so they are used instead of the defined default values.

Once Compat-5.1 is properly installed and configured, all that is needed to install any binary or Lua module is to place it on the corresponding package.cpath or package.path respectively.

Reference

This section gives the API details for the module developers and users. For more information about the Lua 5.1 package system please check the Lua 5.1 documentation or the original package proposal on the Lua mailing list.

Lua Reference

module (name, ...)
Creates a module. The function creates a new global table name (if it does not exists) and sets it as the environment of the new module. It is also set as the value of package.loaded[name] in order to be returned by require function. Function module also defines three names in the new namespace: _NAME, the module name; _M the new environment, itself; and _PACKAGE, the package name. module also receives a sequence of functions which will be called receiving the new environment as its unique parameter. By using a new empty table as the environment, the module would not have access to the previous global environment, so any global value needed by the module must be stored in a local variable before calling module. This default behavior could be changed by passing the function package.seeall as a second argument to module; Then, global visibility will be allowed to the new environment.
require (name)
Loads a package. First, checks whether is is already loaded by looking at table package.loaded with the given name as the key. Otherwise, it checks for a function at table package.preload using name as the key. If it cannot find a function, it looks for a file name in the path package.path; if found, the file is loaded with loadfile and run. Otherwise, require looks for name in the path package.cpath; if found, it tries to call function luaopen_name on that library to open it.
Returns: the content of package.loaded[name] after the execution of the whole file/function.

C Reference

static void luaL_module (lua_State *L, const char *libname,
const luaL_reg *l, int nup)
Modified version of luaL_openlib which stores the table where it opens the library in package.loaded[libname]

Examples

Suppose the file m1.lua is as follows:

local string = require"string"

module("m1")

local function format_words (x)
    return string.gsub (x, "(%w)(%w*)", function (i,s)
        return string.upper(i)..string.lower(s)
    end)
end

function format (x)
    return "prefix"..format_words(x).."sufix"
end

that would define a module called m1 with a public function format and a private function format_words. A possible use of the module would be:

require"m1"

assert (m1)
s = m1.format ("this is a test string")
print(s)

Valid XHTML 1.0!

$Id: manual.html,v 1.20 2006/03/03 15:12:02 tomas Exp $