[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Overriding the default 'require' in libLua (offer)
- From: Peter Cawley <lua@...>
- Date: Wed, 4 Jan 2012 17:52:04 +0000
On Wed, Jan 4, 2012 at 5:36 PM, Paul Bergen <bergen.p0@gmail.com> wrote:
> We have our own application, written in C, that allows users to embed
> snippets of Lua which our C program then executes at various times.
> Rather than writing all the Lua code directly inline, our users want
> to be able to have common modules with shared code that they can
> include with a 'require'. If they put this shared code in a file,
> like mycode.lua, and put the file in the same folder as our C program,
> it works fine. However, we have our own user interface and don't want
> to put these stray files in our program directory. Rather, we will
> compress them and bundle them in our own data files.
>
> So this means the 'require' in Lua will error out and won't find the
> file. So when we create the Lua state in our C app, we want to
> override the built-in 'require' to instead point to our own C
> function. In our C function, it should be identical to the stock Lua
> require, except that if the fopen() command fails, we want to have our
> own code which retrieves the contents of the files ourself, from our
> own data store. We won't be parsing the contents or doing anything
> with them. Just putting them in a (char *) buffer and handing it back
> to the stock Lua require function to process the same as if it had
> opened the file itself with fopen().
>
> Anybody know how to do this? And if anybody cares to write the C code
> to do this, I'll be happy to paypal/wire some money for it. I'm not
> too familiar with libLua and under time pressure.
I am assuming a C function called GetContents. It receives as a
parameter the string passed to require(), and it either returns NULL
or returns a pointer to the file contents and stores the file size in
the given parameter.
const char* GetContents(const char* name, size_t* size_out);
This can then be adapted in a pattern similar to loader_Lua from Lua's
loadlib.c:
static int loader_Custom(lua_State *L) {
size_t size;
const char *name = luaL_checkstring(L, 1);
const char *content = GetContents(name, &size);
if(content) {
lua_pushfstring("@%s", name);
if(luaL_loadbuffer(L, content, size, lua_tostring(L, -1)) != 0)
luaL_error(L, "error loading module " LUA_QS ":\n\t%s", name,
lua_tostring(L, -1));
} else {
lua_pushfstring("\n\tno file " LUA_QS, name);
}
return 1;
}
This function can then be linked into require()'s pipeline by
executing the following code (after the base libraries have been
initialised on L):
luaL_loadstring(L, "table.insert(package.loaders, 3, ...)");
lua_pushcfunction(L, loader_Custom);
lua_call(L, 1, 0);
That was very quickly thrown together from memory, and not tested, so
it might not even compile.