[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Ability to change C module by mere file renaming (Lua 5.1)
- From: Wim Couwenberg <w.couwenberg@...>
- Date: Mon, 28 Nov 2005 20:10:30 +0100
Hi Asko,
> Now, why make it so complicated? Why not just say, that in the
> absence of "luaopen_myfilename()" function, a "luaopen_init()" (or
> similar) will be called.
What we currently do is to use a different (non-standard) loader that
can handle specially named C modules. We use that to have e.g. a flat
directory structure (for DLL's) but still use a hierarchical "dotted"
module name. You'll find the (pseudo)code below. Since we don't use
the standard cloader, a boot script typically replaces the package
loaders entries with some of our own. These special loaders are
statically linked --as byte code-- into our Lua "kernel" to avoid
bootstrap problems. [BTW Currently the official package system does
not provide a way to gracefully alter the loaders table (e.g. replace
just the cloader) since the loaders can not be identified... Or am I
missing something here?] Here is a simple but effective loader
factory that we use (pseudo code):
-- create a C loader. The split argument is used to split the module
-- name in a name for the binary file and a name for the entry point
-- in the binary. If split is not specified then the default splitter
-- 'csplitter' is used. If the split function does not return two
-- parts then the entire loader is skipped. This allows a loader to
-- only respond to module names that match some special pattern.
local function csplitter(modname)
local _, _, fname, entry = string.find(modname, "^([^%-]+)%-(.+)")
if not fname then
fname = modname
entry = modname
end
fname = string.gsub(fname, "%.", "\\")
entry = "luaopen_" .. string.gsub(entry, "%.", "_")
return fname, entry
end
function package.cloader(path, split)
split = split or csplitter
return function(modname)
local fname, entry = split(modname)
if fname and entry then
local fpath = findfile(fname, path)
if fpath then
return assert(loadfunc(fpath, entry),
entry .. " not found in " .. fpath)
end
end
end
end
Now you can install special loaders like so:
package.loaders[1] = preloader
-- a specific binary module loader...
package.loaders[2] = package.cloader(mypath, mysplitter)
-- the standard binary module loader
package.loaders[3] = package.cloader(package.cpath)
This works very well (for us at least) and is quite flexible.
--
Wim