lua-users home
lua-l archive

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


Hi Phillip
 
Thanks for your detailed reply. I think I am winning on this now, I am pretty green with this userdata stuff, so I tried a slightly different solution to keep things simple for now (avoiding c closures).
 
Geoff
 
> To: lua-l@lists.lua.org
> From: siffiejoe@gmx.net
> Date: Sat, 9 Nov 2013 00:28:45 +0100
> Subject: Re: Lua userdata question
>
> Am 08.11.2013 22:34 schröbte Geoff Smith:
> >
> > local a = Foo.new()
> > a:setx(3) -- this works as per the example
> >
> > a.fred = 123 <-- how do I get this to work
> > print(a.fred) <-- how do I get this to work
> >
> > Any tips please on how I would change the C api code to make this work in the above example. My failed attempt I added a __newindex and __index into the Foo_meta table, and some associated C code.
> >
> > The __newindex worked but the __index didn't work as I had overlooked the fact it was already pointing at the methods table.
>
> You put a function instead of the methods table into the `__index` field
> of the metatable. This function first tries to lookup a given key in the
> methods table (which can be passed to the function via an upvalue), and
> then compares the given key with the names of the struct fields to
> return field values (or the other way around). I use the following code
> for situations like this ...
>
>
> static int dispatch( lua_State* L ) {
> lua_CFunction pindex;
> /* try method table first */
> if( lua_istable( L, lua_upvalueindex( 1 ) ) ) {
> lua_pushvalue( L, 2 ); /* duplicate key */
> lua_rawget( L, lua_upvalueindex( 1 ) );
> if( !lua_isnil( L, -1 ) )
> return 1;
> lua_pop( L, 1 );
> }
> pindex = lua_tocfunction( L, lua_upvalueindex( 2 ) );
> return pindex( L );
> }
>
> void moon_propindex( lua_State* L, luaL_Reg const* methods,
> int nups, lua_CFunction pindex ) {
> int top = lua_gettop( L );
> if( methods != NULL ) {
> luaL_checkstack( L, nups + 3, "too many upvalues" );
> lua_newtable( L );
> for( ; methods->func; ++methods ) {
> int i = 0;
> for( i = 0; i < nups; ++i )
> lua_pushvalue( L, top-nups+i+1 );
> lua_pushcclosure( L, methods->func, nups );
> lua_setfield( L, top+1, methods->name );
> }
> if( nups > 0 ) {
> lua_replace( L, top-nups+1 );
> lua_pop( L, nups-1 );
> }
> } else {
> lua_pop( L, nups );
> lua_pushnil( L );
> }
> if( pindex ) {
> lua_pushcfunction( L, pindex );
> lua_pushcclosure( L, dispatch, 2 );
> }
> }
>
> `pindex` is a function that handles the struct fields by doing a series
> of string comparisons[1] and pushing the corresponding value. The other
> arguments are the same as for `luaL_setfuncs`[2].
>
> [1]: http://lua-users.org/lists/lua-l/2013-03/msg00878.html
> [2]: http://www.lua.org/manual/5.2/manual.html#luaL_setfuncs
>
> >
> > Thanks for any help
> >
> > Geoff
> >
>
> Philipp
>
>
>
>
>