lua-users home
lua-l archive

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


Paul Moore wrote:
Maybe the simplest way would be a small tweak to liolib.c to expose a C API for resetting the FILE* handles that io.stdin/out/err point to. I can do this locally, but would such a change be considered for inclusion in the next release of Lua?

With a bit more reading, the following *seems* to work, and doesn't require modifying liolib.c. Can anyone confirm if it's correct? It's a really ugly hack, but I can live with that :-)

/* IO hack. This replaces the io library's idea of stdin/out/err
 * with 3 new FILE* handles, without altering the C stdin/out/err
 * values.
 *
 * It's a hugely ugly hack, fiddling with the internals of the io
 * library. Tested with 5.1.2, may or may not work with other
 * versions...
 */
void hackio(lua_State *L, FILE *in, FILE *out, FILE *err) {
    FILE **pf;
    lua_getglobal(L, "io"); /* Get the IO library */
    lua_pushstring(L, "open");
    lua_gettable(L, -2); /* io, io.open */
    lua_getfenv(L, -1); /* io, io.open, io.open's env */
    lua_getglobal(L, "io"); /* io, open, env, io */

    lua_pushstring(L, "stdin");
    lua_gettable(L, -2); /* io, open, env, io, io.stdin */
    pf = (FILE **)lua_touserdata(L, -1);
    *pf = in;
    lua_rawseti(L, -3, 1); /* IO_INPUT = 1 */

    lua_pushstring(L, "stdout");
    lua_gettable(L, -2); /* io, open, env, io, io.stdout */
    pf = (FILE **)lua_touserdata(L, -1);
    *pf = out;
    lua_rawseti(L, -3, 2); /* IO_OUTPUT = 2 */

    lua_pushstring(L, "stderr");
    lua_gettable(L, -2); /* io, open, env, io, io.stderr */
    pf = (FILE **)lua_touserdata(L, -1);
    *pf = err;
    lua_pop(L, 5);
}

Paul.