예제 #1
0
//----------------------------------------------------------------//
// userdata -> memberTable -> refTable -> interfaceTable
// userdata is the object
// memberTable is for ad hoc members added by the scripter
// refTable is for ad hoc mambers added by the engine
// interfaceTable is the 'class' table - methods and constants
// __index looks in membertTable then *skips* refTable to fall back on interfaceTable
void MOAILuaObject::BindToLua ( MOAILuaState& state ) {

	assert ( !this->mUserdata );
	
	if ( MOAILuaRuntime::IsValid ()) {
		MOAILuaRuntime::Get ().RegisterObject ( state, *this );
	}
	
	MOAILuaClass* type = this->GetLuaClass ();
	assert ( type );
	
	// both singletons and instances may be bound to a userdata
	state.PushPtrUserData ( this ); // userdata
	
	// for now, singletons are just userdata with no add'l metatables
	// so only build the metatable stack if we're *not* a singleton
	if ( !type->IsSingleton ()) {
		// instances get the 'full stack' of metatables
		lua_newtable ( state ); // ref table
		lua_newtable ( state ); // member table
		type->PushInterfaceTable ( state ); // interface table
		this->MakeLuaBinding ( state );
	}
	
	// and take a weak ref back to the userdata	
	this->mUserdata.SetRef ( state, -1 );
	assert ( !lua_isnil ( state, -1 ));
	
	// NOTE: we have to do this *after* mUserdata has been initialized as LuaRetain calls PushLuaUserdata
	// which in turn calls BindToLua if there is no mUserdata...
	if ( type->IsSingleton ()) {
		this->LuaRetain ( this ); // create a circular reference to 'pin' the userdata
	}
}
예제 #2
0
//----------------------------------------------------------------//
void MOAILuaObject::BindToLuaWithTable ( MOAILuaState& state ) {

	assert ( !this->mUserdata );
	assert ( state.IsType ( -1, LUA_TTABLE ));
	
	MOAILuaClass* type = this->GetLuaClass ();
	assert ( type );
	
	// create and initialize a new userdata
	state.PushPtrUserData ( this );
	
	// create and initialize the private table
	lua_newtable ( state );
	
	// set the ref to the private table
	lua_pushvalue ( state, -3 );
	lua_setfield ( state, -2, LUA_MEMBER_TABLE_NAME );
	
	// initialize the private table
	lua_pushcfunction ( state, MOAILuaObject::_gc );
	lua_setfield ( state, -2, "__gc" );
	
	lua_pushcfunction ( state, MOAILuaObject::_tostring );
	lua_setfield ( state, -2, "__tostring" );
	
	lua_pushcfunction ( state, MOAILuaObject::_index );
	lua_setfield ( state, -2, "__index" );
	
	lua_pushcfunction ( state, MOAILuaObject::_newindex );
	lua_setfield ( state, -2, "__newindex" );
	
	// make the interface table the instance table's meta
	type->PushInterfaceTable ( state );
	lua_setmetatable ( state, -2 );
	
	// grab a ref to the instance table; attach it to the userdata
	this->mInstanceTable = state.GetWeakRef ( -1 );
	lua_setmetatable ( state, -2 );
	
	// and take a ref back to the userdata	
	if ( this->GetRefCount () == 0 ) {
		this->mUserdata.SetWeakRef ( state, -1 );
	}
	else {
		this->mUserdata.SetStrongRef ( state, -1 );
	}
	
	// overwrite the member table
	lua_replace ( state, -2 );
	
	assert ( !lua_isnil ( state, -1 ));
}
예제 #3
0
//----------------------------------------------------------------//
void MOAILuaObject::BindToLua ( MOAILuaState& state ) {

	assert ( !this->mUserdata );
	
	MOAILuaClass* type = this->GetLuaClass ();
	assert ( type );
	
	// create and initialize a new userdata
	state.PushPtrUserData ( this );
	
	// create and initialize the member table
	lua_newtable ( state );
	
	lua_pushvalue ( state, -1 );
	lua_setfield ( state, -2, "__index" );
	
	lua_pushvalue ( state, -1 );
	lua_setfield ( state, -2, "__newindex" );
	
	lua_pushcfunction ( state, MOAILuaObject::_gc );
	lua_setfield ( state, -2, "__gc" );
	
	lua_pushcfunction ( state, MOAILuaObject::_tostring );
	lua_setfield ( state, -2, "__tostring" );
	
	// attach the member table to the userdata
	lua_pushvalue ( state, -1 );
	lua_setmetatable ( state, -3 );
	
	// grab a ref to the member table
	this->mMemberTable = state.GetWeakRef ( -1 );
	
	// stack:
	// -1: member table
	// -2: userdata
	
	// create an empty ref table and attach it to the member table
	lua_newtable ( state );
	
	lua_pushvalue ( state, -1 );
	lua_setmetatable ( state, -3 );
	
	// stack:
	// -1: ref table
	// -2: member table
	// -3: userdata
	
	// push the interface table and attach it to the ref table
	type->PushInterfaceTable ( state );
	
	lua_pushvalue ( state, -1 );
	lua_setmetatable ( state, -3 );
	
	// stack:
	// -1: interface table
	// -2: ref table
	// -3: member table
	// -4: userdata
	
	// use the interface table as the ref table's __index
	lua_setfield ( state, -2, "__index" );
	
	// stack:
	// -1: ref table
	// -2: member table
	// -3: userdata
	
	lua_pop ( state, 2 );
	
	// stack:
	// -1: userdata
	
	// and take a ref back to the userdata	
	if ( this->GetRefCount () == 0 ) {
		this->mUserdata.SetWeakRef ( state, -1 );
	}
	else {
		this->mUserdata.SetStrongRef ( state, -1 );
	}
	
	assert ( !lua_isnil ( state, -1 ));
}
예제 #4
0
//----------------------------------------------------------------//
int MOAILuaClass::_extendSingleton ( lua_State* L ) {

	MOAILuaState state ( L );
	
	// upvalues:
	// 1: singleton userdata
	// 2: class table
	
	// set the userdata
	MOAILuaObject* luaData = ( MOAILuaObject* )state.GetPtrUserData ( lua_upvalueindex ( 1 ));
	state.PushPtrUserData ( luaData );
	
	// clone the class table
	state.CloneTable ( lua_upvalueindex ( 2 ));
	
	lua_pushvalue ( state, -1 );
	lua_setfield ( state, -2, "__index" );

	lua_pushvalue ( state, -1 );
	lua_setfield ( state, -2, "__newindex" );
	
	// add getClassName to class table
	lua_pushvalue ( L, 1 );
	lua_pushcclosure ( L, _getUpvalue, 1 );
	lua_setfield ( L, -2, "getClassName" );
	
	// copy the extended userdata
	lua_pushvalue ( L, -2 );
	
	// copy the extended table
	lua_pushvalue ( L, -2 );
	
	// push the 'extend' method with the singleton userdata and extended class table upvalues
	lua_pushcclosure ( L, _extendSingleton, 2 );
	
	// set the extended 'extend' method...
	lua_setfield ( L, -2, "extend" );

	// stack:
	// -1: extended class table
	// -2: extended userdata
	
	// call the extender
	if ( state.IsType ( 2, LUA_TFUNCTION )) {
		lua_pushvalue ( L, 2 );
		lua_pushvalue ( L, -2 );
		lua_pushvalue ( L, lua_upvalueindex ( 2 ));
		state.DebugCall ( 2, 0 );
	}
	
	// stack:
	// -1: extended class table
	// -2: extended userdata
	
	// set the table as a metatable on the userdata
	lua_setmetatable ( L, -2 );
	
	// and we're done
	cc8* classname = state.GetValue < cc8* >( 1, "" );
	lua_setglobal ( state, classname );
	return 0;
}