Open daurnimator opened 13 years ago
This sounds like a neat idea. Do you want to try implementing this in a fork?
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.
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. :>
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
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.