I have the following scenario:
One class named "Base" and second class named "Derived" which derives from "Base". I use metatables to support inheritance in Lua. However I need a solution for checking if passed userdata inherits from specified class.
static int BaseGetMyVar(lua_State *state)
{
Base* base = *(Base**)luaL_checkudata(state, 1, "Base");
//Base* base = *(Base**)lua_touserdata(state, 1);
lua_pushinteger(state, base->GetMyVar());
return 1;
}
When I pass "Derived" udata to this method I get:
HelloWorld.lua:17: calling 'getMyVar' on bad self (Base expected, got userd
ata)
How do I check inheritance? So I can pass either Base or Derived.
Current solutions I've found:
http://lua-users.org/lists/lua-l/2005-06/msg00000.html
http://lua-users.org/lists/lua-l/2007-04/msg00324.html
https://github.com/diegonehab/luasocket/blob/master/src/auxiliar.c
Proposal by siffiejoe(Thanks)
https://github.com/siffiejoe/lua-moon#moon_defcast
Another solution found by accident:
http://lua-users.org/lists/lua-l/2013-06/msg00492.html
My own solution(I like to own things )
void* luaL_checkclass(lua_State *L, const char *classname, int objidx)
{
if(!luaL_getmetafield(L, objidx, "__index"))
return NULL;
lua_getfield(L, -1, "__name");
if(lua_type(L, -1) != LUA_TSTRING)
return NULL;
char const* basename = lua_tostring(L, -1);
lua_pop(L, 2);
if(strcmp(basename, classname) != 0)
luaL_typeerror(L, objidx, classname);
return lua_touserdata(L, objidx);
}
I came up with my own idea. This requires metatable to have field __name(Lua 5.3 implements this, but you can still add this field on your own in previous versions).
More detailed:
Each metatable I register in Lua owns __index field which is either assigned to self or if it has a base class it is assigned to base class. The table at __index owns __name field which is the name of the class... we can just compare the names.
If we pass Derived object to Base method now it will work just fine.
luaL_checkudata()
replacement automatically calls the registered function to cast the pointer to the correct type. – siffiejoe