Lua Binary Modules |
|
VersionNotice: This page pertains to an earlier version of Lua (4.0 and 5.0beta) using a loadmodule
extension. Lua 5.1 uses package.loadlib
and require
. Lua 5.0 uses loadlib
.)
Note: LuaCheia is a portable, maintained distribution of Lua 5.0 which includes and relies on the loadmodule support initiated here.
This page includes a patch to Lua 4.0.1 that adds a loadmodule
function to the default Lua interpreter. This page also lists some binary modules that can be loaded using loadmodule
. These binary modules can extend the functionality of the default Lua interpreter with native code, without having to recompile anything. This makes it very easy for end-users to access useful libraries, and especially combinations of libraries, that would otherwise require recompiling source code for the desired platforms.
A modified interpreter is needed to use the binary modules listed on this page. Source and binaries are linked below. This code was mostly written by IgnacioCastano. It was slightly modified by ThatcherUlrich.
To apply the patch: unpack the correct Lua distribution into a clean directory. Do a cd
to the top of the directory and run patch. For example, say you saved lua.tar.gz and the above patch file in ~/src:
cd ~/src tar -xzvf lua.tar.gz mv lua-4.0.1 lua-4.0.1-loadmodule cd lua-4.0.1-loadmodule patch -p1 < ../lua-4.0-loadmodule-2002-11-21.patch
Be sure to look through the config
file before building, to make sure options are set for your platform.
The binaries below were compiled using the standard Lua 4.0.1 distribution, with the addition of the above patch. Download and use as-is.
[GNU/Linux-i386] | [Win32] | Mac | *BSD | Solaris
In your Lua script, do:
loadmodule("modulename")
That will dynamically load the code from the module, and initialize a binding to Lua. See the documentation for each module for details on how to use it from Lua.
The loadmodule function returns two values. A boolean value that determines if loadmodule suceeded and a string describing the library (in case of suceed) or describing the error (in other case).
ok, str = loadmodule "modulename" if not ok then error( str ) else print( "using " .. str ) end
Or in most cases you will do:
assert( loadmodule "modulename" )
And if modulename doesn't exist it will print:
Lua libraries are assumed to be prefixed with 'lua' to distinguish wrapper libraries from their wrapped counterpart. So, when you do do:
loadmodule("SDL")
you are loading the luaSDL
library. Additionally each platform has its own naming . Currently loadmodule is supported under Win32 and under systems that support DLFCN (Linux, OSX, and most flavours of UNIX).
For example, on Win32 libraries have the '.dll' extension, so the library name for luaSDL
would be:
luaSDL.dll
While on Linux systems it would be:
libluaSDL.so
However, in your lua script you don't have to care about system conventions and you just do: loadmodule("SDL")
.
The library search paths are system dependant.
Linux searches the libraries in the following sequence:
SunOs? searches the libraries in the following sequence:
Windows searches the libraries in the following sequence:
Additionally, luamodule looks for the module in a custom path before in the predefined search paths. That path is set by the global key LUA_LIBPATH. If the key doesn't exist, the custom path is looked up in the LUA_LIBPATH enviroment variable. That should allow you to use newer versions of the libraries than the installed on your system.
A Lua binary module is a platform-specific shared library (for example, a .so under most Unix's, or a .DLL under Win32) which exports these two special functions:
const char* luaLM_version(void); int luaLM_import(lua_State* L);
The function luaLM_version()
should return the value of LUA_VERSION that your module was compiled against; for example it should usually look like this in your source code:
const char* luaLM_version(void) { return LUA_VERSION; }
loadmodule
calls this function first, to make sure that the binary module is compatible with the Lua interpreter it is being loading into.
The function luaLM_import(lua_State* L)
is the function that is called by loadmodule
in order to implement your bindings. This is where you bind your module's functions and variables to the given lua_State
, using the regular Lua API.
It is highly recommended that you put all your bindings in a namespace. That is, all of the functions and values which you bind to Lua should be contained within a table. See LTN7 [1] for an explanation of Lua namespaces. It is recommended that the name of this table correspond to the name of your module. For example, the luaSDL
module, loaded by loadmodule("SDL")
, puts all of its bindings in a table named "SDL". The user is free to assign a different name to this table, if desired, for convenience.
Note: loadmodule
does not enforce the use of namespaces. But your users will probably be happier if you stick to them.
todo: explain why static state in the module is dangerous
todo: advice and example using tolua
Module authors: add your module to the list below, with a short description. Include a link to a wiki or web page where users can get a full description of the module, and download modules binaries (and source, if available).
Here is a list of binary modules that can be used with the above interpreter. (Many of these modules can also be integrated with Lua in a more conventional way by compiling the source for your platform and statically linking with your own custom interpreter.)
I updated the source patch: added some Makefile changes to better support Linux .so's. .so's and executables now have $(V) appended (so the interpreter is lua-4.0
and the main lib is liblua-4.0.so
. Also new binaries, a tarball with the executable and .so's. - ThatcherUlrich
Thatcher: There are some errors in the patch, if you change the name of the static libraries, you also have to change the targets in src/Makefile and src/lib/Makefile. You have also removed the .def files. You can actually generate them by commenting one line in the Makefile and redefining LUA_API and LUALIB_API, but I think it's easier to just use the given def files without touching anything. If someone also has problems with the new patch, the previous one is still here: [patch].- IgnacioCastano
I have uploaded a [zip] containing all sources and the project files for my current tree of lua-loadmodule. -MartinSpernau
I've modified loadmodule so that it ignores the revision number when checking the version. Here is the new [patch]. If nobody reports any bug I will update the above link in a few days.- IgnacioCastano
There is a new patch for lua-5.0-beta here: [patch]. It's not fully test, so use it with care.- IgnacioCastano
The loadmodule addition for lua-5 is excellent; I am using it to make a lua-5 LuaSqlite loadable binary module. However, wouldn't it be nice if the semantics were identical to [Import (TN11)]? This would make modules less dependent on a global name space.
To be honest, I think LTN11 introduces complexity to solve problems that aren't actually problems in practice. The fact is, modules need unique names, so I think it's less confusing to just resolve name clashes directly, and stick with LTN7 conventions. -ThatcherUlrich
With respect, I think LTN11 introduces little (if any) complexity and solves several problems -- although they might not be everybody's problems. For example, it allows the simultaneous use of two implementations of the same interface (two versions of the same module, if you prefer), which is extremely handy for testing. It also makes sandboxing modules more practical, and it opens the possibility of having multiple instances of a module which has internal state (such as readline, or Lua itself). From a C perspective, the "extra complexity" is simply that the module open function uses a table provided as an argument instead of adding it directly to the global namespace; the table itself is then provided by the package system. -RiciLake