lua-users home
lua-l archive

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


Hi Sean,
yes very helpful, thank you ... this also clears my problem - I now
understand this main difference betwen the (nice) BitArray example in
Roberto's "Programming in Lua" and the meta-access of the _G table.

On Fri, Oct 15, 2021 at 12:18 AM Sean Conner <sean@conman.org> wrote:
>
> It was thus said that the Great Flyer31 Test once stated:
> > Hi,
> > I would like to install a metatable for global environment _G from C code.
> >
> > http://lua-users.org/wiki/DetectingUndefinedVariables
> >
> > gives a way to do this in Lua code (see the function GLOBAL_lock) on this page.
> >
> > function GLOBAL_lock(t)
> >   local mt = getmetatable(t) or {}
> >   mt.__newindex = lock_new_index
> >   setmetatable(t, mt)
> > end
> >
> > I tried to use the following code in my C program:
> >
> > void GLOBAL_lock (lua_State *L) {
> >   luaL_newmetatable( L, "_G"));
> >   lua_pushvalue(L, -1); /* duplicate the metatable */
> >   lua_setfield(L, -2, "__index");
> >   lua_pushcfunction( L, lock_new_index);
> >   lua_setfield( L, -2, "__newindex");
> >   luaL_setmetatable( L, "_G");
> > }
> >
> > This compiles fine, and if I check lua_gettop at end of this function,
> > also all fine, also luaL_getmetatable will then return me some table
> > for "_G"... . So it looks as if it has worked.
> >
> > But my function lock_new_index  (int lock_new_index( lua_State *L) {
> > ... } ) is never invoked.
> >
> > Can anybody give me some hint, what code in my C program might be
> > wrong / missing to get this run?
>
>   The solution you want is (assuming Lua 5.2 or higher here):
>
>         static int foo___index   (lua_State *L);
>         static int foo___newindex(lua_State *L);
>
>         static luaL_Reg const metatable[] =
>         {
>           { "__index"    , foo___index    } ,
>           { "__newindex" , foo___newindex } ,
>           /* other metatable methods as required */
>           { NULL , NULL }
>         };
>
>         /*-----------------------------------------------------------------
>         ; Obtain the global table.  We don't use "_G" as this is just a
>         ; convenience value and one I wouldn't fully rely upon.  Following
>         ; the Lua manual, a reference to the global table is stored in the
>         ; registry.  So we get it from there.
>         ;------------------------------------------------------------------*/
>
>         lua_geti(L,LUA_REGISTRYINDEX,LUA_RIDX_GLOBALS); /* obtain _G */
>         luaL_newlib(L,metatable);                       /* create metatable */
>         lua_setmetatable(L,-2);                         /* and set it */
>
>   The functions luaL_setmetatable() and lual_getmetatable() are really meant
> to be used for userdata.  The name parameter isn't the name of a global
> variable, but instead a name indentifying that particular metatable.  For
> example, I create a new userdata type foo and associate a metatable for it:
>
>         static int foo___index    (lua_State *L);
>         static int foo___newindex (lua_State *L);
>         static int foo___len      (lua_State *L);
>
>         static luaL_Reg const foo_metatable[] =
>         {
>           { "__index"    , foo___index    } ,
>           { "__newindex" , foo___newindex } ,
>           { "__len"      , foo___len      } ,
>           { NULL         , NULL           }
>         };
>
>         luaL_newmetatable(L,"TYPE_FOO");
>         luaL_setfuncs(L,foo_metatable,0);
>
>   Then, when a new foo is created:
>
>         Foo *foo = luaL_newuserdata(L,sizeof(Foo));
>         luaL_setmetatable(L,"TYPE_FOO");
>
>   Alternatively (to remain compatible with Lua 5.1):
>
>         Foo * foo = luaL_newuserdata(L,sizeof(Foo));
>         luaL_getmetatable(L,"TYPE_FOO");
>         lua_setmetatable(L,-2);
>
>   -spc (Hope that clears it up some)