lua-users home
lua-l archive

[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 :-)