lua-users home
lua-l archive

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


2009/12/3 Sebastian Wolff <sw@allmech.tuwien.ac.at>:
> So far so good. It is working, but the code is the opposite of being
> elegant. (1) I would like to eliminate the need of the global Lua variables
> __index and __oldindex.
> (2) I would like to eliminate the script itself.
> (3) I would like to eliminate the need of registering my 2 new functions.
>
> For (1) and (2) I think what could help me is to know how I can get the
> metatable of a locally created object. Unfortunately I do not know how to
> create the userdata value "TMMatrix(3,3)" from C since that code is behind
> some blackbox wrapper, i.e. performing the Lua code
>        local metaarray = getmetatable(tm.TMMatrix(1,1))
> on C level. Once I have the metatable on stack I should be able to retrieve
> the metatable field "__index" (at least I hope so).

/* get tm.TMMatrix */
lua_getglobal(L, "tm");
lua_getfield(L, -1, "TMMatrix");
lua_replace(L, -2);
/* push arguments */
lua_pushnumber(L, 1);
lua_pushnumber(L, 1);
/* call tm.TMMatrix, with one result on the stack */
lua_call(L, 2, 1);
/* get the matrix metatable */
lua_getmetatable(L, -1);
/* remove the matrix, keep the metatable */
lua_replace(L, -2);

> For (3) it would be nice to be able to perform the Lua code
>        metaarray.__index = tm.TMMatrix_redefined_index
> in such a way that I do not need to register the function

Following the code above (assuming the metatable is on the top of the stack):

lua_getfield(L, -1, "__index");
lua_pushcclosure(L, my_own_index, 1); /* keep the old index as first upvalue */
lua_setfield(L, -2, "__index");
lua_getfield(L, -1, "__newindex");
lua_pushcclosure(L, my_own_newindex, 1); /* keep the old newindex as
first upvalue */
lua_setfield(L, -2, "__newindex");
lua_pop(L, 1); /* remove the metatable from the stack */

> "tm.TMMatrix_redefined_index". You said this is possible (I would agree with
> that), but I didn't figure out, how - Maybe, if I can solve (1) and (2),
> then I can simply change the function pointer on C level which is stored on
> the Lua stack?

In your new function, you can access the old index from upvalues:

static int my_own_index(lua_State* L)
{
  /* get the old index */
  lua_pushvalue(L, lua_upvalueindex(1));
  /* put it below the parameters on the stack */
  lua_insert(L, 1);
  /* call it, with as many parameters as you have, and keeping all results */
  lua_call(L, lua_gettop(L)-1, LUA_MULTRET); /* -1 is because you
inserted the oldindex function itself */
  /* return as many results as the old index gave you */
  return lua_gettop(L);
}

Same for newindex.

Now, if you want to avoid creating an object of type TMMatrix, that's
possible. All you have to do is try to find the metatable directly. I
don't know where SWIG is storing metatables, but maybe people with
some SWIG for Lua experience can help you there.