lua-users home
lua-l archive

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


On Thu, May 03, 2012 at 11:46:19AM -0400, Andrew Budd wrote:
> Bear with me if I'm misunderstanding something.
> 
> I have written a lua library in C, and am using metatables for methods.
>  What I would like to do is add additional methods to those metatables from
> Lua.  The issue seems to be that I can't access the handle for the
> metatable, and even if I could, it's not clear that I would be able to add
> a function to the table.  Am I barking up the wrong tree here?  or am I
> missing something obvious?
> 

I usually add a special routine, "interpose", which allows adding methods to
a class. It resides in the same table as the constructor for the object. In
the following example, interpose takes 2 or 3 arguments. In the 2 argument
form it just takes a method name and a function, stores the function in the
metatable, and returns the previous entry (which might be stored in a local
variable so it can be called by the new routine). The 3 argument form takes
an additional class name as the MIME library I'm wrapping has subclasses for
headers, entities, etc, but no other way to directly access a constructor
for those classes.

static int lm_interpose(lua_State *L) {
	enum lm_class type;

	switch (lua_gettop(L)) {
	case 2:
		type = LM_MIME;

		break;
	case 3:
		type = lm_checkclass(L, 1);

		break;
	default:
		return luaL_error(L, "internal MIME error: wrong number of arguments (%d) to interpose", lua_gettop(L));
	} /* switch(top) */

	luaL_getmetatable(L, lm_strclass(type));
	lua_getfield(L, -1, "__index");

	lua_pushvalue(L, -4); /* push method name */
	lua_gettable(L, -2);  /* push old method */

	lua_pushvalue(L, -5); /* push method name */
	lua_pushvalue(L, -5); /* push new method */
	lua_settable(L, -4);  /* replace old method */

	return 1; /* return old method */
} /* lm_interpose() */

static const luaL_Reg lm_globals[] = {
	{ "open",      &lm_open },
	{ "interpose", &lm_interpose },
	{ NULL,   NULL }
}; /* lm_globals[] */