lua-users home
lua-l archive

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


Wesley-
Your code looks solid and I'm able to implement with minor edits to deal with accessing userdata 'environments' in Lua 5.2 alpha. Thank you very much!

Gaspard-
Your Lua code confirmed what I was doing wrong all along.  Thanks to you as well!

The major point I was missing is when meta.__index is passed the userdata and function key, I didn't connect to the fact I was only needing to return the function and not actually call the function.  Now I understand why VARGS were never present...

In hindsight, the Lua Reference Manual explained [via gettable_event] everything - a captivating document indeed.

Now for some badly needed sleep ;)

Tom Skwara



I've implemented attributes with the following metamethods and setup code:

usr_attr_mt(
lua_State *L,
luaL_reg *methods,
luaL_reg *getters,
luaL_reg *setters
) {
for(int i=0; methods[i].name; i++) {
lua_pushcfunction(L, methods[i].func);
lua_setfield(L, -2, methods[i].name);
}

lua_newtable(L);
if(getters) {
for(int i=0; getters[i].name; i++) {
lua_pushcfunction(L, getters[i].func);
lua_setfield(L, -2, getters[i].name);
}
}
lua_setfield(L, -2, "__getters");


lua_newtable(L);
if(setters) {
for(int i=0; setters[i].name; i++) {
lua_pushcfunction(L, setters[i].func);
lua_setfield(L, -2, setters[i].name);
}
}
lua_setfield(L, -2, "__setters");
}

usr_attr_index(lua_State *L) {
// first check metatable:
lua_getmetatable(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if(lua_isnil(L, -1)) {
lua_pop(L, 1); // bad result; but leave metatable there...
// next try __getters:
lua_pushstring(L, "__getters");
lua_rawget(L, -2);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if(lua_type(L, -1) == LUA_TFUNCTION) {
lua_pushvalue(L, 1);
int err = lua_pcall(L, 1, 1, 0);
if(err) {
luaL_error(L, "error indexing %s.%s: %s\n",
lua_tostring(L, 1),
lua_tostring(L, 2),
lua_tostring(L, -1));
}
} else {
lua_pop(L, 3); // non-getter, __getters, metatable
// try fenv
lua_getfenv(L, 1);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
}
}
return 1;
}



usr_attr_newindex(lua_State *L) {

// find setter:
lua_getmetatable(L, 1);
lua_pushstring(L, "__setters");
lua_rawget(L, -2);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
// call setter:
if(lua_type(L, -1) == LUA_TFUNCTION) {
lua_pushvalue(L, 1);
lua_pushvalue(L, 3);
int err = lua_pcall(L, 2, 0, 0);
if(err) {
luaL_error(L, "error indexing %s.%s: %s\n",
lua_tostring(L, 1),
lua_tostring(L, 2),
lua_tostring(L, -1));
}
} else {
lua_pop(L, 1); // non-setter
}
lua_pop(L, 2); // __setters, metatable

// store the value in the fenv:
lua_getfenv(L, 1);
lua_pushvalue(L, 2);
lua_pushvalue(L, 3);
lua_rawset(L, -3);
lua_pop(L, 1); // fenv
return 0;
}