[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Full userdata and metamethods
- From: liam mail <liam.list@...>
- Date: Sat, 7 Nov 2009 21:51:24 +0000
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
end
mt1["__eq"] = equal
mt2["__eq"] = equal
t1 = {}
setmetatable(t1,mt1)
t2 = {}
setmetatable(t2,mt2)
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.
http://www.lua.org/manual/5.1/manual.html#2.8
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 \
end");
luaL_loadbuffer(s,chunk.c_str(),chunk.size(),"userChunk");
lua_pcall(s,0,LUA_MULTRET,0);
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);
lua_pushvalue(*m_lua,mt1);
lua_setmetatable(*m_lua,w1);
Int_wrapper* wrapper2 = static_cast<Int_wrapper*>(lua_newuserdata(s, sizeof(Int_wrapper)));
int w2 = lua_gettop(s);
lua_pushvalue(s,mt2);
lua_setmetatable(s,w2);
wrapper1->i = wrapper2->i = 1;
lua_remove(s,mt1);
lua_remove(s,mt1);
lua_pcall(s,2,LUA_MULTRET,0);
int result = lua_tointeger(s,-1);
CPPUNIT_ASSERT_EQUAL(1,result);
lua_close(s);
Could some confirm that this should or should not work, if it should not could you please explain why?
Thanks