lua-users home
lua-l archive

RE: How to know calling convention inside __index function

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


John Labenski wrote:
> print(udata.GetStuff)
> print(udata.GetStuff())
> print(udata:GetStuff())
> 
> udata.SetStuff(5)
> udata.SetStuff = 5
> udata:SetStuff(5)
> 
> [...]
> 
> I am most interested in knowing the difference between udata.GetStuff
> <==> udata:GetStuff() udata.SetStuff = 5 <==> udata:SetStuff(5) 
You are mixing syntatic sugars, metamethods and a confused idea of how
userdata setters/getters work. Here is equivalent code, without the
syntax sugar and with explicit metamethod access:
udata.GetStuff
getmetatable(udata).__index(udata, "GetStuff")
-- __index always get two params
udata.GetStuff()
getmetatable(udata).__index(udata, "GetStuff")()
-- here you just add an extra () pair
udata:GetStuff()
getmetatable(udata).__index(udata, "GetStuff")(udata)
-- here with an additionnal param inside the last () pair
udata.SetStuff(5)
getmetatable(udata).__index(udata, "SetStuff")(5)
-- here you pass 5 to the function returned by __index
udata.SetStuff = 5
getmetatable(udata).__newindex(udata, "SetStuff", 5)
-- __newindew always get three params
udata:SetStuff(5)
getmetatable(udata).__index(udata, "SetStuff")(udata, 5)
-- using : you insert an additionnal param in the setter call
Now to fix this mess you have to decide if you want explicit
getters/setters in Lua or not.
Without getter/setter, you need to overide both __index and __newindex.
Example:
-- In Lua you write:
udata.Stuff = 5
print(udata.Stuff)
/* In C you write */
int my_index(lua_State* L)
{
 somestruct_t* data = (somestruct_t*)lua_touserdata(L, 1);
 const char* field = lua_tostring(L, 2);
 if (!strcmp(field, "Stuff"))
 {
 lua_pushnumber(L, data->Stuff);
 return 1;
 }
 return 0;
}
int my_newindex(lua_State* L)
{
 somestruct_t* data = (somestruct_t*)lua_touserdata(L, 1);
 const char* field = lua_tostring(L, 2);
 if (!strcmp(field, "Stuff"))
 {
 data->Stuff = lua_tonumber(L, 3);
 }
 return 0;
}
With getter/setter, you only need to override __index, but you have to
create two additionnal functions. Example:
-- In Lua you write:
udata:SetStuff(5)
print(udata:GetStuff())
/* In C you write */
int my_GetStuff(lua_State* L)
{
 somestruct_t* data = (somestruct_t*)lua_touserdata(L, 1);
 lua_pushnumber(L, data->Stuff);
 return 1;
}
int my_SetStuff(lua_State* L)
{
 somestruct_t* data = (somestruct_t*)lua_touserdata(L, 1);
 data->Stuff = lua_tonumber(L, 2);
 return 0;
}
int my_index(lua_State* L)
{
 somestruct_t* data = (somestruct_t*)lua_touserdata(L, 1);
 const char* field = lua_tostring(L, 2);
 if (!strcmp(field, "GetStuff"))
 {
 lua_pushcfunction(L, my_GetStuff);
 return 1;
 }
 else if (!strcmp(field, "SetStuff"))
 {
 lua_pushcfunction(L, my_SetStuff);
 return 1;
 }
 return 0;
}
If something is still not clear, fell free to ask for more details :-)

AltStyle によって変換されたページ (->オリジナル) /