/* * __call metafunction of type references. Searches for and calls * a constructor for the type. Returns nil if the constructor is not * found or if the arguments are invalid. Throws an error if the constructor * generates an exception. */ private int callConstructor(LuaCore.lua_State luaState) { var validConstructor = new MethodCache(); IReflect klass; object obj = translator.getRawNetObject(luaState, 1); if (obj.IsNull() || !(obj is IReflect)) { translator.throwError(luaState, "trying to call constructor on an invalid type reference"); LuaLib.lua_pushnil(luaState); return(1); } else { klass = (IReflect)obj; } LuaLib.lua_remove(luaState, 1); var constructors = klass.UnderlyingSystemType.GetConstructors(); foreach (var constructor in constructors) { bool isConstructor = matchParameters(luaState, constructor, ref validConstructor); if (isConstructor) { try { translator.push(luaState, constructor.Invoke(validConstructor.args)); } catch (TargetInvocationException e) { ThrowError(luaState, e); LuaLib.lua_pushnil(luaState); } catch { LuaLib.lua_pushnil(luaState); } return(1); } } string constructorName = (constructors.Length == 0) ? "unknown" : constructors[0].Name; translator.throwError(luaState, String.Format("{0} does not contain constructor({1}) argument match", klass.UnderlyingSystemType, constructorName)); LuaLib.lua_pushnil(luaState); return(1); }
/* * Pushes a new object into the Lua stack with the provided * metatable */ private void pushNewObject(LuaCore.lua_State luaState, object o, int index, string metatable) { if (metatable == "luaNet_metatable") { // Gets or creates the metatable for the object's type LuaLib.luaL_getmetatable(luaState, o.GetType().AssemblyQualifiedName); if (LuaLib.lua_isnil(luaState, -1)) { LuaLib.lua_settop(luaState, -2); LuaLib.luaL_newmetatable(luaState, o.GetType().AssemblyQualifiedName); LuaLib.lua_pushstring(luaState, "cache"); LuaLib.lua_newtable(luaState); LuaLib.lua_rawset(luaState, -3); LuaLib.lua_pushlightuserdata(luaState, LuaLib.luanet_gettag()); LuaLib.lua_pushnumber(luaState, 1); LuaLib.lua_rawset(luaState, -3); LuaLib.lua_pushstring(luaState, "__index"); LuaLib.lua_pushstring(luaState, "luaNet_indexfunction"); LuaLib.lua_rawget(luaState, (int)LuaIndexes.Registry); LuaLib.lua_rawset(luaState, -3); LuaLib.lua_pushstring(luaState, "__gc"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.gcFunction); LuaLib.lua_rawset(luaState, -3); LuaLib.lua_pushstring(luaState, "__tostring"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.toStringFunction); LuaLib.lua_rawset(luaState, -3); LuaLib.lua_pushstring(luaState, "__newindex"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.newindexFunction); LuaLib.lua_rawset(luaState, -3); } } else { LuaLib.luaL_getmetatable(luaState, metatable); } // Stores the object index in the Lua list and pushes the // index into the Lua stack LuaLib.luaL_getmetatable(luaState, "luaNet_objects"); LuaLib.luanet_newudata(luaState, index); LuaLib.lua_pushvalue(luaState, -3); LuaLib.lua_remove(luaState, -4); LuaLib.lua_setmetatable(luaState, -2); LuaLib.lua_pushvalue(luaState, -1); LuaLib.lua_rawseti(luaState, -3, index); LuaLib.lua_remove(luaState, -2); }
/* * Pushes a CLR object into the Lua stack as an userdata * with the provided metatable */ internal void pushObject(LuaCore.lua_State luaState, object o, string metatable) { int index = -1; // Pushes nil if (o.IsNull()) { LuaLib.lua_pushnil(luaState); return; } // Object already in the list of Lua objects? Push the stored reference. bool found = objectsBackMap.TryGetValue(o, out index); if (found) { LuaLib.luaL_getmetatable(luaState, "luaNet_objects"); LuaLib.lua_rawgeti(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.lua_type(luaState, -1); if (type != LuaTypes.Nil) { LuaLib.lua_remove(luaState, -2); // drop the metatable - we're going to leave our object on the stack return; } // MetaFunctions.dumpStack(this, luaState); LuaLib.lua_remove(luaState, -1); // remove the nil object value LuaLib.lua_remove(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); }
public object getAsObject(LuaCore.lua_State luaState, int stackPos) { if (LuaLib.lua_type(luaState, stackPos) == LuaTypes.Table) { if (LuaLib.luaL_getmetafield(luaState, stackPos, "__index")) { if (LuaLib.luaL_checkmetatable(luaState, -1)) { LuaLib.lua_insert(luaState, stackPos); LuaLib.lua_remove(luaState, stackPos + 1); } else { LuaLib.lua_settop(luaState, -2); } } } object obj = translator.getObject(luaState, stackPos); return(obj); }
/* * __call metafunction of CLR delegates, retrieves and calls the delegate. */ private int runFunctionDelegate(LuaCore.lua_State luaState) { LuaCore.lua_CFunction func = (LuaCore.lua_CFunction)translator.getRawNetObject(luaState, 1); LuaLib.lua_remove(luaState, 1); return(func(luaState)); }