Lua Binary Modules

lua-users home
wiki

The conventions, docs and code here are a proposal by ThatcherUlrich for a "community standard" Binary Module system for Lua. Consider it an "alpha" version, subject to change. Please direct comments and criticism to the Lua mailing list.

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.


Lua 4.0.1 with loadmodule

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.

source

[lua-4.0.1-loadmodule.patch]

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.

binaries

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

User Instructions

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:

error: assertion failed! cannot load module 'modulename'

Library naming conventions

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").

Library search paths

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.

Instructions for module authors

functions to export

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.

namespaces

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

A simple Tutorial

can be found under BinaryModuleTutorial. It describes a way to turn any given Lua extension into a loadmocule ready dynamic link library.

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).


Binary Modules

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.)


''Could it be possible to return module's own version info upon success ? ie. now loadmodule("fuzzy") prints "using fuzzy"; maybe "fuzzy-x.yy.zz" may be better for version dependent usage ? Or... Returning a "Info" table whose fields are Developer, Version, Licence, Description,..'' -Hakki Dogusan

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


RecentChanges · preferences
edit · history
Last edited December 24, 2009 5:11 pm GMT (diff)