lua-ev icon indicating copy to clipboard operation
lua-ev copied to clipboard

Interoperability with lua file objects

Open daurnimator opened this issue 13 years ago • 4 comments

Could you add a way to use normal lua file descriptors? See: http://www.lua.org/source/5.1/liolib.c.html#getiofile

For usabilitiy; it might be nice if there was a tolibevio(x) funtion that would take a lua file object, socket object or other io types and convert them to an io object for libev.

daurnimator avatar Oct 22 '11 23:10 daurnimator

This sounds like a neat idea. Do you want to try implementing this in a fork?

brimworks avatar Oct 23 '11 14:10 brimworks

I'm rather compiler-poor at the moment; but I can point you to the code at https://github.com/rrthomas/luaposix/blob/master/lposix.c#L583 this will transform a lua file object into a fd for you.

Otherwise for sockets, as you know you have getfd.

So, as a C function, I'd check if the metatable is the file metatable; if so use the above routine; otherwise just try and call the getfd method..... Other libraries can then be made to work by adding getfd functions to their methods.

daurnimator avatar Oct 23 '11 23:10 daurnimator

On Linux you use fileno() to fetch the fd from the FILE* within the lua_Stream (Lua's file handle type). On Windows you use _fileno() :-)

So it would involve a function like this:

static int
standard_error(lua_State * L, int err, char * (*errfunc)(int), char * fname)
{
    char * msg = errfunc(err);

    lua_pushnil(L);

    if (NULL == fname)
        lua_pushstring(L, msg);
    else
        lua_pushfstring(L, "%s: %s", fname, msg);

    lua_pushinteger(L, err);

    return 3;
}

static int
file_to_fd(lua_State * L, FILE * stream)
{
    int fd = -1;

#ifdef _WIN32
    fd = _fileno(stream);
#else
    fd = fileno(stream);
#endif

    if (-1 == fd)
#ifdef _WIN32
        return standard_error(L, fd, &str_error, "_fileno()");
#else
        return standard_error(L, fd, &str_error, "fileno()");
#endif

    return fd;
}

First you would:

luaL_testudata(L, index, LUA_FILEHANDLE)

If the result is non-NULL you pass that pointer to file_to_fd(), if not, you treat the first arg as an immediate fd in lua_Number form. ;-) file_to_fd() would be called by io_new() in io_lua_ev.c

Maybe I'll work on this at the weekend...\

PS: Yes standard_error() is a bit over-engineered but in another project I swap out str_error() with gai_error() sometimes. :>

blitmap avatar May 14 '13 02:05 blitmap

What worked for me. Adapt it to win32 like Blitmap does if you need that

typedef struct myluaL_Stream {
	FILE *f;
	lua_CFunction closef;
} myluaL_Stream;

//* int fd getFD(file file) Returns the file descriptor associated with a Lua file
static int l_getFD(lua_State* L){
	lua_pushinteger(L, fileno(((myluaL_Stream*)luaL_checkudata(L, 1, "FILE*"))->f));
	return 1;
}

I had to copy the struct because it wasn't public in 5.1 but still works with the latest revisions of Lua 5.1 and/or LuaJIT and doesn't change in future versions. https://www.lua.org/source/5.2/lauxlib.h.html#luaL_Stream https://www.lua.org/source/5.3/lauxlib.h.html#luaL_Stream https://www.lua.org/source/5.4/lauxlib.h.html#luaL_Stream

Since it's the first member it is also possible to do something like

	FILE** file = luaL_checkudata(L, 1, "FILE*");
	lua_pushinteger(L, fileno(*file));

But doesn't really gain you anything and makes it harder to get what's actually going on, IMHO

Trendyne avatar Aug 26 '22 18:08 Trendyne