lua-users home
lua-l archive

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


Per the discussions about strings for looking up values, one of my standard Lua utility routines is roughly:

	int pushTableForKey( lua_State* L, int sourceIndex, const void* udkey ) {
		// Normalize sourceIndex to avoid problems with relative addresses after the push.
		lua_pushlightuserdata( L, (void*) udkey );
		lua_gettable( L, sourceIndex );
		if( !lua_isnil( L, -1 ) ) return 0;
		lua_pop( L, 1 );
		lua_newtable( L );
		return 1;
	}

This is used as follows:

	static char keyData = 0;

	if( pushTableForKey( L, LUA_REGISTRYINDEX, &keyData ) ) {
		// Initialize the table since we just created it
	}

Object creation, for example, can look like:

	lua_newuserdata( L, sizeof( Object ) );

	static char Object_RegistryKey = 0;

	if( pushTableForKey( L, LUA_REGISTRYINDEX, &Object_RegistryKey ) ) {
		// Initialize object metatable
	}

	lua_setmetatable( L, -2 );

For type-checking, however, I think the upvalue approach is probably the best option if you don't need to support class hierarchies -- i.e., you can live with new versions of the method being pushed for each metatable.

So long as one doesn't need upvalues for the methods, this could actually be encapsulated into code that took the table of methods and built little stub closures to do the type checking if space was viewed as more valuable than raw speed. (The stub closures can either use a separate allocation to hold the function pointer or can use multiple upvalues to reference the method table and an index in the table or can simply abuse the fact that though a void* and a function pointer are not interconvertible according to the spec, in practice they are.)

Hmm. It may be time to go write a new set of native object support logic.

Mark