lua-users home
lua-l archive

Re: Possible to add methods in Lua to metatables defined in C?

[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[] */

AltStyle によって変換されたページ (->オリジナル) /