First of all. You have already defined some USEFUL userdata and some OTHERUSEFUL userdata. Each one has a list of functions defined in C.
I will assume that OTHERUSEFUL will inherit from USEFUL. To do that, Lua uses metatables.
In C code, one should do the following:
<OTHERUSEFUL C-code>
void *otheruseful_instance = lua_newuserdata(L, sizeof(void));
lua_newtable(L);
luaL_setmetatable(L, "USEFUL"); // inheritance starts HERE
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index"); // necessary
// add functions specific for OTHERUSEFUL
// DO NOT forget to add
lua_pushcclosure(L, &asstring, 0);
lua_setfield(L, -2, "__tostring");
lua_pushcclosure(L, &gcollect, 0);
lua_setfield(L, -2, "__gc");
// optionally
lua_pushliteral(L, "OTHERUSEFUL");
lua_setfield(L, -2, "__name");
...
lua_setmetatable(L, -2); inheritance ends HERE
...
< END >
However, if you apply the function luaL_checkudata, you still have the problem of incompatibility with the functions inherited by OTHERUSEFUL from USEFUL.
To solve this problem, I added the following function to USEFUL or anywhere it might be required (a userdata that will be inherited from).
< C-code>
// replace every use of luaL_checkudata by myL_checkudata.
int checkmetatable(lua_State *L) {
if (lua_getmetatable(L, -2) {
lua_replace(L, -3);
if (lua_rawequal(L, -1, -2))
return 1;
}
return 0;
}
void *myL_testudata(lua_State *L, int ud, const char *tname) {
void *p = lua_touserdata(L, ud);
if (p != NULL) {
if (lua_getmetatable(L, ud)) {
luaL_getmetatable(L, tname);
if (!(lua_rawequal(L, -1, -2) || checkmetatable(L)))
p = NULL;
lua_pop(L, 2);
return p;
}
}
return NULL;
}
void *myL_checkudata(lua_State *L, int ud, const char *tname) {
void *p = myL_testudata(L, ud, tname);
if (p == NULL) { // value is not a userdata with a metatable
// error signal
}
return p;
}
< END >
If it looks cryptic just take a look at "luaxlib.c"; you will find how the original functions were written.
Cheers,
// Carlos