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 byrequirefunction. Functionmodulealso defines three names in the new namespace:_NAME, the module name;_Mthe new environment, itself; and_PACKAGE, the package name.modulealso 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 callingmodule. This default behavior could be changed by passing the functionpackage.seeallas a second argument tomodule; 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.loadedwith the given name as the key. Otherwise, it checks for a function at tablepackage.preloadusing name as the key. If it cannot find a function, it looks for a file name in the pathpackage.path; if found, the file is loaded withloadfileand run. Otherwise,requirelooks for name in the pathpackage.cpath; if found, it tries to call functionluaopen_nameon that library to open it.
Returns: the content ofpackage.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_openlibwhich stores the table where it opens the library inpackage.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)