Writing LuaCheia modules
You can write pure Lua modules if you want; modules are not by any
means required to have a binary component.
Pick a name/namespace
You need to pick a module name, which will also serve as a module
namespace. This name needs to be a word which is valid both as part
of a filename, and as a Lua identifier. Examples:
- pcre
- fuzzy
- cheia
- SDL
- wx
- SQL
See Module names for a list of currently-used module names; you
should avoid name collisions with this list.
Binding to your C code
For the basic interface, use any method you want. Including:
- Handmade C API bindings
- GluaX
- tolua (when it's available for 5.0)
- LuaSWIG
Set up your code to be built as a shared library. See
"src/modules/fuzzy" for a small sample; also see below under
‘Building’.
Loading your shared library into LuaCheia
You need to write a Lua stub for your module, which does the actual
binding to your module. The result is to create a global table, with
the name of your module. This table should contain all the data and
code of your module. Aside from creating and populating this table,
and loading other required modules, your stub should have no side
effects.
You can use any supported method of loading your binary module,
including:
- The loadlib function (built-in Lua 5.0 feature)
-
loadmodule (similar to loadlib, but has safer versioning), available
in LuaCheia as cheia.loadmodule
- GluaX (adds binding wrappers), available in LuaCheia as
cheia.gluaload
Building
The LuaCheia project uses autoconf and automake to create extremely
portable Makefiles. If you want your modules to be as cross-platform
as possible, we recommend using autoconf and automake, following the
examples in "src/modules". Also, all modules included in the LuaCheia
project must be able to be built using autoconf and automake.
However, autoconf and automake are not very intuitive to use, if you
haven't used them extensively. Nothing about the LuaCheia
module-loading architecture cares how you actually build the modules,
so if you are making a module for yourself, or to be distributed
independently of the LuaCheia project, you can use whatever tools you
want.
Your module should be built as a shared library for the target
platform (e.g. DLL on Windows, .so on Linux, OSX and most Unixes).
Your module should dynamically link to Lua, using the filenames:
- liblua-5.dll and liblualib-5.dll on Windows
- liblua.so.5 and liblualib.so.5 on Linux
- liblua.5.dylib and liblualib.5.dylib on OSX
See also [Unknown reference: ABI] for some details about how the components of
LuaCheia are built for different platforms.
Building using the LuaCheia framework
To add a module into to the luacheia source tree and build it using
the existing framework, you need to follow these steps:
- Make a subdirectory for your module's source files, under
"src/modules". E.g. "src/modules/yourmodule".
- Create a "Makefile.am" file in this dir. It's probably easiest to
copy one from an existing module, and then edit it to reference the
name of your module and your source files.
- Add "src/modules/yourmodule/Makefile" to the list at the end of
configure.ac
- Add the module name to the LC_ALL_MODULES list in "configure.ac"
Now you're ready to try building. First do this in the root of the
luacheia tree, to set up your configure script and "Makefile.in"s:
# aclocal |
|
# autoconf |
|
# autoheader |
|
# automake |
|
|
If necessary, fix any errors in "configure.ac" and your "Makefile.am", and
repeat the above commands.
Now, do this to set up the actual "Makefile"s, specific to your system:
And finally, to try building:
Last but not least, to link all the shared libraries and put them in
their appropriate directories:
cheia.load stub-loader scripts
LuaCheia has one canonical function to load external functionalities
(modules): cheia.load.
cheia.load takes one parameter, the module namespace as a string:
cheia.load(“pcre”) |
|
cheia.load(“SDL_mixer”) |
|
|
(optionally it can be passed true/false as second parameter, which
will 'force' reloading of a module if true)
cheia.load will follow the semantics described in Module path conventions
to find a ‘stub loader’ script which will then implement the actual
functionallity to ‘load’ a given module.
Minimum structure of a stub-loader script
-- begin stub-loader script for module 'modname' |
|
return cheia.loadmodule(“modname”) |
|
-- end of stubloader for 'modname' |
|
|
So the module named 'modname' would be loaded like so:
LC> cheia.load("modname") |
|
|
What happens internally
-
cheia.load searches and loads the stub-loader script.
- It runs the stub-loader script. The script should return true on
success, or false plus an error message on failure.
In case of success, cheia.load returns true. If any of the steps
fails, then cheia.load returns false plus an error message.
Examples and notes
Note: Keep in mind that the stub-loader script is not limited in
functionality to loading binary (dll/so) extensions. A ‘module’ could
completly be defined only by it's stub-loader script (Lua-only
module), it can be a mix of binary-extension (Lua extending a binary
module with helper functions) or a basic ‘loader’ for a binary
extension.
Also note that there are several loading mechanisms for LuaCheia as described above.
It is totally up to the module author to choose the loading mechanism
to be used for a given module.
|