Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interoperability with lua file objects #5

Open
daurnimator opened this issue Oct 22, 2011 · 4 comments
Open

Interoperability with lua file objects #5

daurnimator opened this issue Oct 22, 2011 · 4 comments

Comments

@daurnimator
Copy link
Contributor

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.

@brimworks
Copy link
Owner

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

@daurnimator
Copy link
Contributor Author

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.

@blitmap
Copy link
Contributor

blitmap commented May 14, 2013

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. :>

@Trendyne
Copy link

Trendyne commented Aug 26, 2022

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants