lua-users home
lua-l archive

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

This message may or may not have appeared on the mailing list as it was sent went there was a problem with the server, yet I have received newer messages. So I am assuming the first has been lost in the cloud :).
I am sorry if is a duplicate.

I have come across something that I am unsure if it is expected behaviour or a bug and would like some help to identify which it is.
Without going into too much detail I am trying to use the metamethod "__eq" using two full userdata types which both have different metatables yet the same metamethod. According to what I have reread in Programming in Lua and the Reference Manual this should work and does so for tables yet not userdata.
Here is the Lua code for tables:
mt1 = {}
mt2 = {}

equal = function (lhs, rhs)
return lhs.i == rhs.i

mt1["__eq"] = equal
mt2["__eq"] = equal
t1 = {}
t2 = {}
t1.i = 1
t2.i = 1
assert(t1 == t2)

As you can see it is two tables with different metables yet with the same metamethod which according to the Reference Manual would work.

When I try a similar thing with full userdata instead of tables the method is not called and it returns false, yet I feel it should not. Here is example C++ code for that, (forgive me it takes a bit more code to do this):
First the userdata structure and the method

struct Int_wrapper{int i;};

int equal(lua_State* s)
    Int_wrapper* i1 = static_cast<Int_wrapper *>( lua_touserdata(s, 1) );
    Int_wrapper* i2 = static_cast<Int_wrapper *>( lua_touserdata(s, 2) );
    lua_pushinteger(s, i1->i == i2->i ? 1 : 0 );
    return 1;

        lua_State* s = luaL_newstate();
        std::string chunk("equal = function (lhs, rhs) \
                          return lhs == rhs \
        lua_getfield(s, LUA_GLOBALSINDEX, "equal");

        luaL_newmetatable(s, "mt1");
        int mt1 = lua_gettop(s);
        luaL_newmetatable(s, "mt2");
        int mt2 = lua_gettop(s);

        lua_pushliteral(s, "__eq");
        lua_pushcfunction(s, &equal);
        lua_settable(s, mt1);

        lua_pushliteral(s, "__eq");
        lua_pushcfunction(s, &equal);
        lua_settable(s, mt2);

        Int_wrapper* wrapper1 = static_cast<Int_wrapper*>(lua_newuserdata(s, sizeof(Int_wrapper)));
        int w1 = lua_gettop(*m_lua);

        Int_wrapper* wrapper2 = static_cast<Int_wrapper*>(lua_newuserdata(s, sizeof(Int_wrapper)));
        int w2 = lua_gettop(s);

        wrapper1->i = wrapper2->i = 1;

        int result = lua_tointeger(s,-1);

Could some confirm that this should or should not work, if it should not could you please explain why?