lua-users home
lua-l archive

Re: Ability to change C module by mere file renaming (Lua 5.1)

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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

AltStyle によって変換されたページ (->オリジナル) /