lua-users home
lua-l archive

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


Reuben Thomas wrote:
> luaposix makes Lua file handles by setting their metatable to the
> FILE* entry from the registry. This is enough to make PUC-Rio Lua
> recognise them as Lua file handles, but not LuaJIT 2.0.0-beta7, which
> has its own internal userdata types system.
> 
> I am unclear from the Lua reference manual whether I ought to expect
> this technique to work or not, that is:

Grabbing the metatable of a different module and attaching it to
your own userdata objects is asking for trouble. You're relying on
an implementation detail.

> luaL_getmetatable(L, LUA_FILEHANDLE); /* LUA_FILEHANDLE is exported
> but undocumented */
> lua_setmetatable(L, n); /* ??? Should this work ??? */

For Lua 5.1, you also need to set the environment table of the
userdata to define the close function. Yes, I know, you already
figured that out, but it's totally undocumented.

That's actually part of the problem, because you'll need to rely
on many more undocumented internals of the VM. E.g. it's nowhere
written down that the userdata object should hold only a pointer
to a FILE *, or what happens if that is NULL, because fopen or
similar failed, or what happens on GC, and so on.

> In LuaJIT, io.type will not return true unless the userdata's private
> udtype field is UDTYPE_IO_FILE, and the only way to get that setting
> is to use a normal Lua io library call which returns a handle
> (AFAICS).

That's deliberate. Amongs other reasons, this is because the
special userdata object contains more than just the FILE *. Any
attempt at injecting a 'made up' userdata is thus rejected.

I do not see an easy and portable way to inherit the standard io.*
methods, unless there's an explicit API function that provides
this functionality.

But it wouldn't be helpful to add such a C API function to LuaJIT
only. Since Lua 5.1 doesn't have this symbol, your library would
fail to load under Lua.

I'd rather add io.fdopen() and fp:fileno(), because these are
useful for the FFI, too. Ok, so you'll need to fetch io.fdopen
once at the start and put it into an upvalue. Not sure if you're
happy with that.

--Mike