/* * Pushes a new object into the Lua stack with the provided * metatable */ private void PushNewObject(LuaState luaState, object o, int index, string metatable) { if (metatable == "luaNet_metatable") { string assemblyQualifiedName = CacheReflection.GetAssemblyQualifiedName(o.GetType()); // Gets or creates the metatable for the object's type LuaLib.LuaLGetMetatable(luaState, assemblyQualifiedName); if (LuaLib.LuaIsNil(luaState, -1)) { LuaLib.LuaSetTop(luaState, -2); LuaLib.LuaLNewMetatable(luaState, assemblyQualifiedName); LuaLib.LuaPushString(luaState, "cache"); LuaLib.LuaNewTable(luaState); LuaLib.LuaRawSet(luaState, -3); LuaLib.LuaPushLightUserData(luaState, LuaLib.LuaNetGetTag()); LuaLib.LuaPushNumber(luaState, 1); LuaLib.LuaRawSet(luaState, -3); LuaLib.LuaPushString(luaState, "__index"); LuaLib.LuaPushString(luaState, "luaNet_indexfunction"); LuaLib.LuaRawGet(luaState, (int)LuaIndexes.Registry); LuaLib.LuaRawSet(luaState, -3); LuaLib.LuaPushString(luaState, "__gc"); LuaLib.LuaPushStdCallCFunction(luaState, metaFunctions.GcFunction); LuaLib.LuaRawSet(luaState, -3); LuaLib.LuaPushString(luaState, "__tostring"); LuaLib.LuaPushStdCallCFunction(luaState, metaFunctions.ToStringFunction); LuaLib.LuaRawSet(luaState, -3); LuaLib.LuaPushString(luaState, "__newindex"); LuaLib.LuaPushStdCallCFunction(luaState, metaFunctions.NewIndexFunction); LuaLib.LuaRawSet(luaState, -3); // Bind C# operator with Lua metamethods (__add, __sub, __mul) RegisterOperatorsFunctions(luaState, o.GetType()); RegisterCallMethodForDelegate(luaState, o); } } else { LuaLib.LuaLGetMetatable(luaState, metatable); } // Stores the object index in the Lua list and pushes the // index into the Lua stack LuaLib.LuaLGetMetatable(luaState, "luaNet_objects"); LuaLib.LuaNetNewUData(luaState, index); LuaLib.LuaPushValue(luaState, -3); LuaLib.LuaRemove(luaState, -4); LuaLib.LuaSetMetatable(luaState, -2); LuaLib.LuaPushValue(luaState, -1); LuaLib.LuaRawSetI(luaState, -3, index); LuaLib.LuaRemove(luaState, -2); }
/* * Pushes a new object into the Lua stack with the provided * metatable */ private void PushNewObject(LuaState luaState, object o, int index, string metatable) { if (metatable == "luaNet_metatable") { // Gets or creates the metatable for the object's type LuaLib.LuaLGetMetatable(luaState, o.GetType().AssemblyQualifiedName); if (LuaLib.LuaIsNil(luaState, -1)) { LuaLib.LuaSetTop(luaState, -2); LuaLib.LuaLNewMetatable(luaState, o.GetType().AssemblyQualifiedName); LuaLib.LuaPushString(luaState, "cache"); LuaLib.LuaNewTable(luaState); LuaLib.LuaRawSet(luaState, -3); LuaLib.LuaPushLightUserData(luaState, LuaLib.LuaNetGetTag()); LuaLib.LuaPushNumber(luaState, 1); LuaLib.LuaRawSet(luaState, -3); LuaLib.LuaPushString(luaState, "__index"); LuaLib.LuaPushString(luaState, "luaNet_indexfunction"); LuaLib.LuaRawGet(luaState, (int)LuaIndexes.Registry); LuaLib.LuaRawSet(luaState, -3); LuaLib.LuaPushString(luaState, "__gc"); LuaLib.LuaPushStdCallCFunction(luaState, metaFunctions.gcFunction); LuaLib.LuaRawSet(luaState, -3); LuaLib.LuaPushString(luaState, "__tostring"); LuaLib.LuaPushStdCallCFunction(luaState, metaFunctions.toStringFunction); LuaLib.LuaRawSet(luaState, -3); LuaLib.LuaPushString(luaState, "__newindex"); LuaLib.LuaPushStdCallCFunction(luaState, metaFunctions.newindexFunction); LuaLib.LuaRawSet(luaState, -3); } } else { LuaLib.LuaLGetMetatable(luaState, metatable); } // Stores the object index in the Lua list and pushes the // index into the Lua stack LuaLib.LuaLGetMetatable(luaState, "luaNet_objects"); LuaLib.LuaNetNewUData(luaState, index); LuaLib.LuaPushValue(luaState, -3); LuaLib.LuaRemove(luaState, -4); LuaLib.LuaSetMetatable(luaState, -2); LuaLib.LuaPushValue(luaState, -1); LuaLib.LuaRawSetI(luaState, -3, index); LuaLib.LuaRemove(luaState, -2); }
/* * Pushes a CLR object into the Lua stack as an userdata * with the provided metatable */ internal void PushObject(LuaState luaState, object o, string metatable) { int index = -1; // Pushes nil if (o == null) { LuaLib.LuaPushNil(luaState); return; } // Object already in the list of Lua objects? Push the stored reference. #if NETFX_CORE bool found = (!o.GetType().GetTypeInfo().IsValueType || o.GetType().GetTypeInfo().IsEnum) && objectsBackMap.TryGetValue(o, out index); #else bool found = (!o.GetType().IsValueType || o.GetType().IsEnum) && objectsBackMap.TryGetValue(o, out index); #endif if (found) { LuaLib.LuaLGetMetatable(luaState, "luaNet_objects"); LuaLib.LuaRawGetI(luaState, -1, index); // Note: starting with lua5.1 the garbage collector may remove weak reference items (such as our luaNet_objects values) when the initial GC sweep // occurs, but the actual call of the __gc finalizer for that object may not happen until a little while later. During that window we might call // this routine and find the element missing from luaNet_objects, but collectObject() has not yet been called. In that case, we go ahead and call collect // object here // did we find a non nil object in our table? if not, we need to call collect object var type = LuaLib.LuaType(luaState, -1); if (type != LuaTypes.Nil) { LuaLib.LuaRemove(luaState, -2); // drop the metatable - we're going to leave our object on the stack return; } // MetaFunctions.dumpStack(this, luaState); LuaLib.LuaRemove(luaState, -1); // remove the nil object value LuaLib.LuaRemove(luaState, -1); // remove the metatable CollectObject(o, index); // Remove from both our tables and fall out to get a new ID } index = AddObject(o); PushNewObject(luaState, o, index, metatable); }