lua-users home
lua-l archive

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


Mike Pall wrote:

Hi,

Vincent Penne wrote:
The problem with that solution is that it complicates greatly the registration of functions, because you have to think in advance of all types that are going to be checked by your function (for example let's say that your function takes 10 arguments, each of different types). You would need to have 10 upvalues for your function, furthermore you would need to remember which upvalue index corresponds to which type.

Of all the Lua libraries I have come across recently, most methods need
exactly one userdata argument (i.e. 'self'). Only a few need two.

Maybe that's because 'doing it the Lua way' suggest a different API style
(e.g. using strings as options or keys, using multiple arguments instead
of wrapping them up into userdata structures).

The case you mention is somewhat common when you have to create a binding
to huge OO-style libraries that have not been designed exclusively for Lua
(GUI libraries come to mind). I'm pretty sure it pays off to autogenerate
the wrapper code in this case. Then juggling around with different metatables
and upvalues really doesn't matter. But performance does.

Actually, that's exactly what I had in mind :) So, yes, it really depends on the context. If your only userdata is self then it's definitely worth putting it as upvalue.

2* lua_rawgeti() + 2* lua_rawseti() plus a few other API calls for the
common code path in luaL_ref(). I guess this is even slower than any
of the registry approaches.


I mean lua_getref, not luaL_ref. Actually, lua_getref is just a lua_rawgeti into the registry (it's a #define). It is faster than the registry approach, I just benchmarked it. It is not surprising because lua_rawgeti is faster than lua_rawget (I think) and there is no string comparison. It's probably slower than the upvalue method however, but I cannot test it simply at the moment since I have a lot of arguments with different types in my functions :)

Here is the code that do what I suggest :

void *luaL_checkudata_ref(lua_State *L, int ud, int ref, char *msg)
{
 void *u;
 if (lua_getmetatable(L, ud)) && (lua_getref(L, ref), 1) &&
     lua_rawequal(L, -1, -2) &&
     (u = lua_touserdata(L, ud))) {
   lua_pop(L, 2);
   return u;
 }
 luaL_argerror(L, 0, msg); /* Never returns. */
 return NULL;
}