lua-users home
lua-l archive

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


2008/9/24 Wesley Smith <wesley.hoke@gmail.com>:
> wows, lot's of questions.

And still, I have only a very partial view of your object system. I
don't know if you assume you used a standard method to do it (there is
no such standard), or used a binding tool to do it for you, but in
either case we can't guess what you did.

>> Can you explain what View is ? Metatable for userdata
> Is that a singleton ? No
> A prototype ? No unless you consider a metatable for a userdata such a  thing
>> class ? No
>> objects userdata, tables ?  the metatable generates userdata from it's factory method  View()
>> How are their methods defined and where are they located ? in the metatable itself
>
>
> So far, I'm basically "deep copying" the View metatable and doing
> setmetatable(ViewCopy, getmetatable(View)).  This seems to be enough
> as I can't do any more than that.

This is a little bit contradictory, if you do the equivalent of
setmetatable(ViewCopy, getmetatable(View)), both Views will point to
the same copy of the metatable, there is no deep copy involved. I'll
describe both cases.

If you actually do a deep copy of the metatable, then each object has
its own metatable and __index metamethod. You can now implement a
__newindex to allow adding/replacing methods at runtime. If __index is
a table, make __newindex point to the same table. If __index is a
function which recognizes hardcoded keys, you have to create a table
and assign it to __newindex, and modify __index to first check that
table for key/value pairs before checking against your hardcoded keys.
If you do something more complex, you'll have to describe what.

If you have shared metatables, then the possibility are reduced.
First, you can't have __index and __newindex be tables. They have to
be functions. These functions should then first look at a per-object
table when called, for example the userdata's environment (which you
have to set at object creation). For example you could do:

int View_clone(lua_State* L) {
  View* original = lua_touserdata(L, 1);
  View* clone = lua_newuserdata(L, sizeof(View));
  /* do some init on clone, eventually using original */
  /* share metatable with original */
  lua_getmetatable(L, 1);
  lua_setmetatable(L, -2);
  /* create a per-object environment */
  lua_newtable(L);
  lua_setfenv(L, -2)
  return 1;
}

int View__index(lua_State* L) {
  View* object = lua_touserdata(L, 1);
  /* first check the environment table */
  lua_getfenv(L, 1);
  lua_pushvalue(L, 2);
  lua_gettable(L, -2);
  /* if the environment table contains that key then return the value */
  if (!lua_isnil(L, -1))
    return 1;
  lua_pop(L, 1); /* pop the nil */
  /* check your hardcoded keys */
  if (lua_isstring(L, 2) && !strcmp(lua_tostring(L, 2), "clone"))
    lua_pushcfunction(L, View_clone);
  else
    lua_pushnil(L);
  return 1;
}

int View__newindex(lua_State* L) {
  /* simply put the key/value pair in the object environment */
  lua_getfenv(L, 1);
  lua_replace(L, 1);
  lua_settable(L, -3);
  return 0;
}