lua-users home
lua-l archive

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


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.