lua-users home
lua-l archive

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


The problem is that this isn't safe. How does Lua know that the pointer you
are passing in really is a userdata? For example, it might have been one at
one point but might have since been collected.

I added essentially the same thing you did and then backed it off since I
didn't have firm evidence that the overhead (definitely noticeable in
profiling) was worth introducing a hole in Lua's integrity guarantees.

The approach we currently use actually involves multiple table lookups to
push a userdata onto the stack:

    lua_pushlightuserdata( L, kMagicKey );
        // kMagicKey just needs to be a unique address
    lua_gettable( L, LUA_REGISTRYINDEX );
    lua_pushlightuserdata( L, objPtr );
    lua_gettable( L, -2 );
    lua_remove( L, -2 );

The item referenced by kMagicKey is a fully-weak table mapping the light
userdata version of the userdata pointers to the actual userdata objects. We
use this sort of key rather than the ref system, because it will work even
with multiple threads running multiple Lua universes.

Two things would help here:

1. Introduce a fully-weak registry. Then we get:

    lua_pushlightuserdata( L, objPtr );
    lua_gettable( L, LUA_WEAKREGISTRYINDEX );
    
2. Recognize that light userdata makes a really useful key for a lot of
things and add support in much the same way getfield was added. That then
leads to:

    lua_getudfield( L, LUA_WEAKREGISTRYINDEX, objPtr );

Or without 1:

    lua_getudfield( L, LUA_REGISTRYINDEX, kMagicKey );
    lua_getudfield( L, -1, objPtr );
    lua_remove( L, -2 );

Mark

on 12/13/06 12:07 AM, Cloud Wu at cloudwu@163.com wrote:

> Hello Lua,
> 
>   lua can only push lightuserdata into the stack, but sometimes we
>   need push a full userdata.
> 
>   When I wrote a gui system in lua, the widget in C get the message
>   from os first, and then I need convert the widget to the lua object
>   for dispatching the message. In fact , my widget have a pointer
>   return by lua_newuserdata , but there is no api to convert back this
>   pointer to a lua object.
> 
>   Now, I create a weak table in registry. Then use luaL_ref to get a
>   reference of the object, and save the reference number in my widget.
>   When I need convert the pointer back to the lua object, I can use
>   the reference number to lookup that weak table .
> 
>   But I think it's a expensive way, Adding a new api lua_pushuserdata
>   to convert the pointer back will much cheaper.
> 
>   --------------
> LUA_API void lua_pushuserdata (lua_State *L, void *p) {
>   Udata *u;
>   lua_lock(L);
>   u = cast(Udata *,p) - 1;
>   setuvalue(L, L->top, u);
>   api_incr_top(L);
>   lua_unlock(L);
> }
>   --------------
> 
>   This api would be unsafe, because the pointer p may be not a
>   userdata alloc by lua , or the userdata has already been collected.
>   But we can use it on our own risk. If someone use it in a wrong way,
>   it's not lua's fault.