|
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 > > > > > |