/* * Creates a new table as a global variable or as a field * inside an existing table */ public void NewTable(string fullPath) { string[] path = fullPath.Split(new char[] { '.' }); int oldTop = LuaLib.lua_gettop(luaState); if (path.Length == 1) { LuaLib.lua_newtable(luaState); LuaLib.lua_setglobal(luaState, fullPath); } else { LuaLib.lua_getglobal(luaState, path[0]); for (int i = 1; i < path.Length - 1; i++) { LuaLib.lua_pushstring(luaState, path[i]); LuaLib.lua_gettable(luaState, -2); } LuaLib.lua_pushstring(luaState, path[path.Length - 1]); LuaLib.lua_newtable(luaState); LuaLib.lua_settable(luaState, -3); } LuaLib.lua_settop(luaState, oldTop); }
/* * Registers the indexing function of CLR objects * passed to Lua */ private void createIndexingMetaFunction(LuaCore.lua_State luaState) { LuaLib.lua_pushstring(luaState, "luaNet_indexfunction"); LuaLib.luaL_dostring(luaState, MetaFunctions.luaIndexFunction); // steffenj: lua_dostring renamed to luaL_dostring //LuaLib.lua_pushstdcallcfunction(luaState, indexFunction); LuaLib.lua_rawset(luaState, (int)LuaIndexes.Registry); }
/* * CAUTION: LuaInterface.Lua instances can't share the same lua state! */ public Lua(LuaCore.lua_State lState) { LuaLib.lua_pushstring(lState, "LUAINTERFACE LOADED"); LuaLib.lua_gettable(lState, (int)LuaIndexes.Registry); if (LuaLib.lua_toboolean(lState, -1)) { LuaLib.lua_settop(lState, -2); throw new LuaException("There is already a LuaInterface.Lua instance associated with this Lua state"); } else { LuaLib.lua_settop(lState, -2); LuaLib.lua_pushstring(lState, "LUAINTERFACE LOADED"); LuaLib.lua_pushboolean(lState, true); LuaLib.lua_settable(lState, (int)LuaIndexes.Registry); luaState = lState; LuaLib.lua_pushvalue(lState, (int)LuaIndexes.Globals); LuaLib.lua_getglobal(lState, "luanet"); LuaLib.lua_pushstring(lState, "getmetatable"); LuaLib.lua_getglobal(lState, "getmetatable"); LuaLib.lua_settable(lState, -3); LuaLib.lua_replace(lState, (int)LuaIndexes.Globals); translator = new ObjectTranslator(this, luaState); LuaLib.lua_replace(lState, (int)LuaIndexes.Globals); LuaLib.luaL_dostring(lState, Lua.init_luanet); // steffenj: lua_dostring renamed to luaL_dostring } _StatePassed = true; }
public Lua() { luaState = LuaLib.luaL_newstate(); // steffenj: Lua 5.1.1 API change (lua_open is gone) //LuaLib.luaopen_base(luaState); // steffenj: luaopen_* no longer used LuaLib.luaL_openlibs(luaState); // steffenj: Lua 5.1.1 API change (luaopen_base is gone, just open all libs right here) LuaLib.lua_pushstring(luaState, "LUAINTERFACE LOADED"); LuaLib.lua_pushboolean(luaState, true); LuaLib.lua_settable(luaState, (int)LuaIndexes.Registry); LuaLib.lua_newtable(luaState); LuaLib.lua_setglobal(luaState, "luanet"); LuaLib.lua_pushvalue(luaState, (int)LuaIndexes.Globals); LuaLib.lua_getglobal(luaState, "luanet"); LuaLib.lua_pushstring(luaState, "getmetatable"); LuaLib.lua_getglobal(luaState, "getmetatable"); LuaLib.lua_settable(luaState, -3); LuaLib.lua_replace(luaState, (int)LuaIndexes.Globals); translator = new ObjectTranslator(this, luaState); LuaLib.lua_replace(luaState, (int)LuaIndexes.Globals); LuaLib.luaL_dostring(luaState, Lua.init_luanet); // steffenj: lua_dostring renamed to luaL_dostring // We need to keep this in a managed reference so the delegate doesn't get garbage collected panicCallback = new LuaCore.lua_CFunction(PanicCallback); LuaLib.lua_atpanic(luaState, panicCallback); //LuaLib.lua_atlock(luaState, lockCallback = new LuaCore.lua_CFunction(LockCallback)); //LuaLib.lua_atunlock(luaState, unlockCallback = new LuaCore.lua_CFunction(UnlockCallback)); }
/* * Sets up the list of objects in the Lua side */ private void createLuaObjectList(LuaCore.lua_State luaState) { LuaLib.lua_pushstring(luaState, "luaNet_objects"); LuaLib.lua_newtable(luaState); LuaLib.lua_newtable(luaState); LuaLib.lua_pushstring(luaState, "__mode"); LuaLib.lua_pushstring(luaState, "v"); LuaLib.lua_settable(luaState, -3); LuaLib.lua_setmetatable(luaState, -2); LuaLib.lua_settable(luaState, (int)LuaIndexes.Registry); }
/* * Creates the metatable for delegates */ private void createFunctionMetatable(LuaCore.lua_State luaState) { LuaLib.luaL_newmetatable(luaState, "luaNet_function"); LuaLib.lua_pushstring(luaState, "__gc"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.gcFunction); LuaLib.lua_settable(luaState, -3); LuaLib.lua_pushstring(luaState, "__call"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.execDelegateFunction); LuaLib.lua_settable(luaState, -3); LuaLib.lua_settop(luaState, -2); }
/* * Navigates a table to set the value of one of its fields */ internal void setObject(string[] remainingPath, object val) { for (int i = 0; i < remainingPath.Length - 1; i++) { LuaLib.lua_pushstring(luaState, remainingPath[i]); LuaLib.lua_gettable(luaState, -2); } LuaLib.lua_pushstring(luaState, remainingPath[remainingPath.Length - 1]); translator.push(luaState, val); LuaLib.lua_settable(luaState, -3); }
/* * Gets a field of the table corresponding to the provided reference * using rawget (do not use metatables) */ internal object rawGetObject(int reference, string field) { int oldTop = LuaLib.lua_gettop(luaState); LuaLib.lua_getref(luaState, reference); LuaLib.lua_pushstring(luaState, field); LuaLib.lua_rawget(luaState, -2); object obj = translator.getObject(luaState, -1); LuaLib.lua_settop(luaState, oldTop); return(obj); }
/* * Pushes the object into the Lua stack according to its type. */ internal void push(LuaCore.lua_State luaState, object o) { if (o.IsNull()) { LuaLib.lua_pushnil(luaState); } else if (o is sbyte || o is byte || o is short || o is ushort || o is int || o is uint || o is long || o is float || o is ulong || o is decimal || o is double) { double d = Convert.ToDouble(o); LuaLib.lua_pushnumber(luaState, d); } else if (o is char) { double d = (char)o; LuaLib.lua_pushnumber(luaState, d); } else if (o is string) { string str = (string)o; LuaLib.lua_pushstring(luaState, str); } else if (o is bool) { bool b = (bool)o; LuaLib.lua_pushboolean(luaState, b); } else if (IsILua(o)) { (((ILuaGeneratedType)o).__luaInterface_getLuaTable()).push(luaState); } else if (o is LuaTable) { ((LuaTable)o).push(luaState); } else if (o is LuaCore.lua_CFunction) { pushFunction(luaState, (LuaCore.lua_CFunction)o); } else if (o is LuaFunction) { ((LuaFunction)o).push(luaState); } else { pushObject(luaState, o, "luaNet_metatable"); } }
/* * Implementation of make_object. Registers a table (first * argument in the stack) as an object subclassing the * type passed as second argument in the stack. */ private int registerTable(LuaCore.lua_State luaState) { if (LuaLib.lua_type(luaState, 1) == LuaTypes.Table) { var luaTable = getTable(luaState, 1); string superclassName = LuaLib.lua_tostring(luaState, 2).ToString(); if (!superclassName.IsNull()) { var klass = FindType(superclassName); if (!klass.IsNull()) { // Creates and pushes the object in the stack, setting // it as the metatable of the first argument object obj = CodeGeneration.Instance.GetClassInstance(klass, luaTable); pushObject(luaState, obj, "luaNet_metatable"); LuaLib.lua_newtable(luaState); LuaLib.lua_pushstring(luaState, "__index"); LuaLib.lua_pushvalue(luaState, -3); LuaLib.lua_settable(luaState, -3); LuaLib.lua_pushstring(luaState, "__newindex"); LuaLib.lua_pushvalue(luaState, -3); LuaLib.lua_settable(luaState, -3); LuaLib.lua_setmetatable(luaState, 1); // Pushes the object again, this time as the base field // of the table and with the luaNet_searchbase metatable LuaLib.lua_pushstring(luaState, "base"); int index = addObject(obj); pushNewObject(luaState, obj, index, "luaNet_searchbase"); LuaLib.lua_rawset(luaState, 1); } else { throwError(luaState, "register_table: can not find superclass '" + superclassName + "'"); } } else { throwError(luaState, "register_table: superclass name can not be null"); } } else { throwError(luaState, "register_table: first arg is not a table"); } return(0); }
/* * 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); }
/* * Creates the metatable for superclasses (the base * field of registered tables) */ private void createBaseClassMetatable(LuaCore.lua_State luaState) { LuaLib.luaL_newmetatable(luaState, "luaNet_searchbase"); LuaLib.lua_pushstring(luaState, "__gc"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.gcFunction); LuaLib.lua_settable(luaState, -3); LuaLib.lua_pushstring(luaState, "__tostring"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.toStringFunction); LuaLib.lua_settable(luaState, -3); LuaLib.lua_pushstring(luaState, "__index"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.baseIndexFunction); LuaLib.lua_settable(luaState, -3); LuaLib.lua_pushstring(luaState, "__newindex"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.newindexFunction); LuaLib.lua_settable(luaState, -3); LuaLib.lua_settop(luaState, -2); }
/* * Navigates a table in the top of the stack, returning * the value of the specified field */ internal object getObject(string[] remainingPath) { object returnValue = null; for (int i = 0; i < remainingPath.Length; i++) { LuaLib.lua_pushstring(luaState, remainingPath[i]); LuaLib.lua_gettable(luaState, -2); returnValue = translator.getObject(luaState, -1); if (returnValue.IsNull()) { break; } } return(returnValue); }
/* * Creates the metatable for type references */ private void createClassMetatable(LuaCore.lua_State luaState) { LuaLib.luaL_newmetatable(luaState, "luaNet_class"); LuaLib.lua_pushstring(luaState, "__gc"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.gcFunction); LuaLib.lua_settable(luaState, -3); LuaLib.lua_pushstring(luaState, "__tostring"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.toStringFunction); LuaLib.lua_settable(luaState, -3); LuaLib.lua_pushstring(luaState, "__index"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.classIndexFunction); LuaLib.lua_settable(luaState, -3); LuaLib.lua_pushstring(luaState, "__newindex"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.classNewindexFunction); LuaLib.lua_settable(luaState, -3); LuaLib.lua_pushstring(luaState, "__call"); LuaLib.lua_pushstdcallcfunction(luaState, metaFunctions.callConstructorFunction); LuaLib.lua_settable(luaState, -3); LuaLib.lua_settop(luaState, -2); }
/* * Implementation of free_object. Clears the metatable and the * base field, freeing the created object for garbage-collection */ private int unregisterTable(LuaCore.lua_State luaState) { try { if (LuaLib.lua_getmetatable(luaState, 1) != 0) { LuaLib.lua_pushstring(luaState, "__index"); LuaLib.lua_gettable(luaState, -2); object obj = getRawNetObject(luaState, -1); if (obj.IsNull()) { throwError(luaState, "unregister_table: arg is not valid table"); } var luaTableField = obj.GetType().GetField("__luaInterface_luaTable"); if (luaTableField.IsNull()) { throwError(luaState, "unregister_table: arg is not valid table"); } luaTableField.SetValue(obj, null); LuaLib.lua_pushnil(luaState); LuaLib.lua_setmetatable(luaState, 1); LuaLib.lua_pushstring(luaState, "base"); LuaLib.lua_pushnil(luaState); LuaLib.lua_settable(luaState, 1); } else { throwError(luaState, "unregister_table: arg is not valid table"); } } catch (Exception e) { throwError(luaState, e.Message); } return(0); }