lua-users home
lua-l archive

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


I am using both :-)

Let me explain:
I have some C++ library from which I get instances of ressources (C++
objects) it provides. These have members, that I expose to LUA.
To do so, I need a 'heavy' userdata, with a metatable fitted with the
__gettable field, which is in fact a table containing the binding functions.

However, once I get such an instance, some queries to the library might
return a pointer to the same instance, if for example I want a list of
instances sharing some features. If I create a new 'heavy' userdata with
this pointer as value, and return it to the LUA script, I cannot compare two
'heavy' userdata objects and declare them equal, even though their inside is
the same.
To avoid this, I keep in the registry a unicity table where a key is a light
userdata with the pointer value, and the value is the 'heavy' userdata with
the same pointer. Each time I need to provide a LUA script with a 'heavy'
userdata (so that the variable has a metatable and its methods can be
accessed), I lookup the light pointer value in the registry and fetch the
corresponding 'heavy' userdata. If I don't find it I add it. That way, for
each resource instance the library can provide there is always exactly one
'heavy' userdata that references it. This is very useful when this userdata
indexes something in a table: whatever I do, when I retrieve a userdata
object related to a given resource, all LUA variables that refer to the same
ressource will be considered equal, and table indexing will work as
expected.
Of course, this reference in the unicity table means that this 'heavy'
userdata can never be garbage collected unless some destroy mechanism is
explicitly invoked by the script, in which case the unicity table entry is
cleared.

Regards,

Benoit.

> -----Original Message-----
> From: Evan Wies [mailto:evan@mindengine.com]
> Sent: jeudi 5 septembre 2002 17:52
> To: Multiple recipients of list
> Subject: Re: Light User Data
> 
> 
> Thanks for the comprehensive answer!
> 
> I'm still figuring whether I should use light userdata or ordinary
> userdata.  Since I'm most interested in wrapping my C++ 
> objects for use
> in Lua, it seems like the ordinary userdata is what I need.
> 
> I'd appreciate feedback on this idea:
> If I have C++ object system with RTTI (my own homegrown or 
> C++'s) _AND_
> I ensure that all the C++ objects I expose in Lua support RTTI, then I
> get the typesafety and I can play around.
> 
> But, I guess the thing I'm still missing is the ability to call Lua
> functions that are tied to an object's type (i.e., invoke 
> methods on the
> light userdata's pointer), since there is no metatable.
> 
> -Evan
> 
> 
> "Edgar Toernig" <froese@gmx.de> wrote in message
> news:<3D76B77F.2AD6EA28@gmx.de>...
> > Evan Wies wrote:
> > > 
> > > I am trying to understand the right way to use the light userdata 
> > > (in Lua 5 of course).
> > > 
> > > As I understand it, light userdata is just a pointer 
> value and has 
> > > no metatable (since it's light) and tag (since it's Lua 5).
> > 
> > Right.  Like numbers.  In fact, formerly, numbers were used 
> to store 
> > C-pointers but it's not save to store pointers in floats.  So the 
> > light userdata was added as a way to store C-pointers within Lua.
> > 
> > You need them any time you want to:
> > 
> >  - map C-pointers to a Lua object.  I.e. you use the registry
> >    as the mapping table: KEY is the light userdata with your
> >    C-pointer and VALUE is the corresponding Lua object:
> > 
> >      create mapping:
> > 	lua_pushlightuserdata(L, <c-pointer>);
> >         lua_pushvalue(L, <index-of-lua-object>);
> >         lua_rawset(L, LUA_REGISTRYINDEX);
> > 
> >      fetch object:
> >         lua_pushlightuserdata(L, <c-pointer>);
> >         lua_rawget(L, LUA_REGISTRYINDEX);
> >         <object on stack>
> > 
> >  - pass C-pointers to functions called from Lua.  You push your
> >    pointer as a light userdata and attach that as an upvalue to
> >    your function.
> > 
> >       create function:
> >         lua_pushlightuserdata(L, <c-pointer>);
> >         lua_pushcclosure(L, <function>, 1);
> >         <function on stack>
> > 
> >       fetch within function:
> >         void *handle = lua_touserdata(L, lua_upvalueindex(1));
> > 
> > 
> > > But, since it lacks any tags, how are you supposed to do anything 
> > > typesafe with this value?
> > 
> > Make sure that you cannot get the wrong type ;-)
> > 
> > <b>As a rule: never export light userdata to Lua scripts!</b>
> > 
> > Use them within your C code and never make them visible outside of 
> > your module.  If you do, a Lua script may bomb your system.
> > 
> > Ciao, ET.
> > 
> > 
> > Obbug: int and longs are not save to store in floats, too...
> > 
>