/* * __index metafunction of base classes (the base field of Lua tables). * Adds a prefix to the method name to call the base version of the method. */ private int getBaseMethod(LuaCore.lua_State luaState) { object obj = translator.getRawNetObject(luaState, 1); if (obj.IsNull()) { translator.throwError(luaState, "trying to index an invalid object reference"); LuaLib.lua_pushnil(luaState); LuaLib.lua_pushboolean(luaState, false); return(2); } string methodName = LuaLib.lua_tostring(luaState, 2).ToString(); if (methodName.IsNull()) { LuaLib.lua_pushnil(luaState); LuaLib.lua_pushboolean(luaState, false); return(2); } getMember(luaState, obj.GetType(), obj, "__luaInterface_base_" + methodName, BindingFlags.Instance | BindingFlags.IgnoreCase); LuaLib.lua_settop(luaState, -2); if (LuaLib.lua_type(luaState, -1) == LuaTypes.Nil) { LuaLib.lua_settop(luaState, -2); return(getMember(luaState, obj.GetType(), obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase)); } LuaLib.lua_pushboolean(luaState, false); return(2); }
/* * 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)); }
/* * 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"); } }
/* * Called by the __index metafunction of CLR objects in case the * method is not cached or it is a field/property/event. * Receives the object and the member name as arguments and returns * either the value of the member or a delegate to call it. * If the member does not exist returns nil. */ private int getMethod(LuaCore.lua_State luaState) { object obj = translator.getRawNetObject(luaState, 1); if (obj.IsNull()) { translator.throwError(luaState, "trying to index an invalid object reference"); LuaLib.lua_pushnil(luaState); return(1); } object index = translator.getObject(luaState, 2); //var indexType = index.GetType(); string methodName = index as string; // will be null if not a string arg var objType = obj.GetType(); // Handle the most common case, looking up the method by name. // CP: This will fail when using indexers and attempting to get a value with the same name as a property of the object, // ie: xmlelement['item'] <- item is a property of xmlelement try { if (!methodName.IsNull() && isMemberPresent(objType, methodName)) { return(getMember(luaState, objType, obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase)); } } catch { } // Try to access by array if the type is right and index is an int (lua numbers always come across as double) if (objType.IsArray && index is double) { int intIndex = (int)((double)index); if (objType.UnderlyingSystemType == typeof(float[])) { float[] arr = ((float[])obj); translator.push(luaState, arr[intIndex]); } else if (objType.UnderlyingSystemType == typeof(double[])) { double[] arr = ((double[])obj); translator.push(luaState, arr[intIndex]); } else if (objType.UnderlyingSystemType == typeof(int[])) { int[] arr = ((int[])obj); translator.push(luaState, arr[intIndex]); } else { object[] arr = (object[])obj; translator.push(luaState, arr[intIndex]); } } else { // Try to use get_Item to index into this .net object //MethodInfo getter = objType.GetMethod("get_Item"); var methods = objType.GetMethods(); foreach (var mInfo in methods) { if (mInfo.Name == "get_Item") { //check if the signature matches the input if (mInfo.GetParameters().Length == 1) { var getter = mInfo; var actualParms = (!getter.IsNull()) ? getter.GetParameters() : null; if (actualParms.IsNull() || actualParms.Length != 1) { translator.throwError(luaState, "method not found (or no indexer): " + index); LuaLib.lua_pushnil(luaState); } else { // Get the index in a form acceptable to the getter index = translator.getAsType(luaState, 2, actualParms[0].ParameterType); object[] args = new object[1]; // Just call the indexer - if out of bounds an exception will happen args[0] = index; try { object result = getter.Invoke(obj, args); translator.push(luaState, result); } catch (TargetInvocationException e) { // Provide a more readable description for the common case of key not found if (e.InnerException is KeyNotFoundException) { translator.throwError(luaState, "key '" + index + "' not found "); } else { translator.throwError(luaState, "exception indexing '" + index + "' " + e.Message); } LuaLib.lua_pushnil(luaState); } } } } } } LuaLib.lua_pushboolean(luaState, false); return(2); }