public ObjectTranslator (Lua interpreter, LuaCore.lua_State luaState) { this.interpreter = interpreter; typeChecker = new CheckType (this); metaFunctions = new MetaFunctions (this); assemblies = new List<Assembly> (); importTypeFunction = new LuaCore.lua_CFunction (ObjectTranslator.importType); loadAssemblyFunction = new LuaCore.lua_CFunction (ObjectTranslator.loadAssembly); registerTableFunction = new LuaCore.lua_CFunction (ObjectTranslator.registerTable); unregisterTableFunction = new LuaCore.lua_CFunction (ObjectTranslator.unregisterTable); getMethodSigFunction = new LuaCore.lua_CFunction (ObjectTranslator.getMethodSignature); getConstructorSigFunction = new LuaCore.lua_CFunction (ObjectTranslator.getConstructorSignature); createLuaObjectList (luaState); createIndexingMetaFunction (luaState); createBaseClassMetatable (luaState); createClassMetatable (luaState); createFunctionMetatable (luaState); setGlobalFunctions (luaState); }
private int registerTableInternal (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; }
static int PanicCallback (LuaCore.lua_State luaState) { string reason = string.Format ("unprotected error in call to Lua API ({0})", LuaLib.lua_tostring (luaState, -1)); throw new LuaException (reason); }
internal void pushCSFunction (LuaCore.lua_CFunction function) { translator.pushFunction (luaState, function); }
private static void DebugHookCallback (LuaCore.lua_State luaState, LuaCore.lua_Debug luaDebug) { var translator = ObjectTranslatorPool.Instance.Find (luaState); var lua = translator.Interpreter; lua.DebugHookCallbackInternal (luaState, luaDebug); }
/* * 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).LuaInterfaceGetLuaTable ()).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"); }
/* * Pushes the entire array into the Lua stack and returns the number * of elements pushed. */ internal int returnValues (LuaCore.lua_State luaState, object[] returnValues) { if (LuaLib.lua_checkstack (luaState, returnValues.Length + 5)) { for (int i = 0; i < returnValues.Length; i++) push (luaState, returnValues [i]); return returnValues.Length; } else return 0; }
/* * Pushes a type reference into the stack */ internal void pushType (LuaCore.lua_State luaState, Type t) { pushObject (luaState, new ProxyType (t), "luaNet_class"); }
/* * Pushes a delegate into the stack */ internal void pushFunction (LuaCore.lua_State luaState, LuaCore.lua_CFunction func) { pushObject (luaState, func, "luaNet_function"); }
private static int getConstructorSignature (LuaCore.lua_State luaState) { var translator = ObjectTranslatorPool.Instance.Find (luaState); return translator.getConstructorSignatureInternal (luaState); }
private int getConstructorSignatureInternal (LuaCore.lua_State luaState) { IReflect klass = null; int udata = LuaLib.luanet_checkudata (luaState, 1, "luaNet_class"); if (udata != -1) klass = (IReflect)objects [udata]; if (klass.IsNull ()) throwError (luaState, "get_constructor_bysig: first arg is invalid type reference"); var signature = new Type[LuaLib.lua_gettop (luaState) - 1]; for (int i = 0; i < signature.Length; i++) signature [i] = FindType (LuaLib.lua_tostring (luaState, i + 2).ToString ()); try { ConstructorInfo constructor = klass.UnderlyingSystemType.GetConstructor (signature); pushFunction (luaState, new LuaCore.lua_CFunction ((new LuaMethodWrapper (this, null, klass, constructor)).invokeFunction)); } catch (Exception e) { throwError (luaState, e); LuaLib.lua_pushnil (luaState); } return 1; }
private int getMethodSignatureInternal (LuaCore.lua_State luaState) { IReflect klass; object target; int udata = LuaLib.luanet_checkudata (luaState, 1, "luaNet_class"); if (udata != -1) { klass = (IReflect)objects [udata]; target = null; } else { target = getRawNetObject (luaState, 1); if (target.IsNull ()) { throwError (luaState, "get_method_bysig: first arg is not type or object reference"); LuaLib.lua_pushnil (luaState); return 1; } klass = target.GetType (); } string methodName = LuaLib.lua_tostring (luaState, 2).ToString (); var signature = new Type[LuaLib.lua_gettop (luaState) - 2]; for (int i = 0; i < signature.Length; i++) signature [i] = FindType (LuaLib.lua_tostring (luaState, i + 3).ToString ()); try { //CP: Added ignore case var method = klass.GetMethod (methodName, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.IgnoreCase, null, signature, null); pushFunction (luaState, new LuaCore.lua_CFunction ((new LuaMethodWrapper (this, target, klass, method)).invokeFunction)); } catch (Exception e) { throwError (luaState, e); LuaLib.lua_pushnil (luaState); } return 1; }
private int unregisterTableInternal (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; }
private static int unregisterTable (LuaCore.lua_State luaState) { var translator = ObjectTranslatorPool.Instance.Find (luaState); return translator.unregisterTableInternal (luaState); }
/* * Gets the CLR object in the index positon of the Lua stack. Returns * delegates as Lua functions. */ internal object getNetObject (LuaCore.lua_State luaState, int index) { int idx = LuaLib.luanet_tonetobject (luaState, index); return idx != -1 ? objects [idx] : null; }
/* * 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); }
/* * Gets the CLR object in the index position of the Lua stack. Returns * delegates as is. */ internal object getRawNetObject (LuaCore.lua_State luaState, int index) { int udata = LuaLib.luanet_rawnetobj (luaState, index); return udata != -1 ? objects [udata] : null; }
/* * 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); }
/* * Gets the values from the provided index to * the top of the stack and returns them in an array. */ internal object[] popValues (LuaCore.lua_State luaState, int oldTop) { int newTop = LuaLib.lua_gettop (luaState); if (oldTop == newTop) return null; else { var returnValues = new List<object> (); for (int i = oldTop+1; i <= newTop; i++) returnValues.Add (getObject (luaState, i)); LuaLib.lua_settop (luaState, oldTop); return returnValues.ToArray (); } }
/* * Gets an object from the Lua stack with the desired type, if it matches, otherwise * returns null. */ internal object getAsType (LuaCore.lua_State luaState, int stackPos, Type paramType) { var extractor = typeChecker.checkType (luaState, stackPos, paramType); return !extractor.IsNull () ? extractor (luaState, stackPos) : null; }
/* * Gets the values from the provided index to * the top of the stack and returns them in an array, casting * them to the provided types. */ internal object[] popValues (LuaCore.lua_State luaState, int oldTop, Type[] popTypes) { int newTop = LuaLib.lua_gettop (luaState); if (oldTop == newTop) return null; else { int iTypes; var returnValues = new List<object> (); if (popTypes [0] == typeof(void)) iTypes = 1; else iTypes = 0; for (int i = oldTop+1; i <= newTop; i++) { returnValues.Add (getAsType (luaState, i, popTypes [iTypes])); iTypes++; } LuaLib.lua_settop (luaState, oldTop); return returnValues.ToArray (); } }
/* * Gets an object from the Lua stack according to its Lua type. */ internal object getObject (LuaCore.lua_State luaState, int index) { var type = LuaLib.lua_type (luaState, index); switch (type) { case LuaTypes.Number: { return LuaLib.lua_tonumber (luaState, index); } case LuaTypes.String: { return LuaLib.lua_tostring (luaState, index); } case LuaTypes.Boolean: { return LuaLib.lua_toboolean (luaState, index); } case LuaTypes.Table: { return getTable (luaState, index); } case LuaTypes.Function: { return getFunction (luaState, index); } case LuaTypes.UserData: { int udata = LuaLib.luanet_tonetobject (luaState, index); return udata != -1 ? objects [udata] : getUserData (luaState, index); } default: return null; } }
/* * Checks if the method matches the arguments in the Lua stack, getting * the arguments if it does. */ internal bool matchParameters (LuaCore.lua_State luaState, MethodBase method, ref MethodCache methodCache) { return metaFunctions.matchParameters (luaState, method, ref methodCache); }
/* * Gets the table in the index positon of the Lua stack. */ internal LuaTable getTable (LuaCore.lua_State luaState, int index) { LuaLib.lua_pushvalue (luaState, index); return new LuaTable (LuaLib.lua_ref (luaState, 1), interpreter); }
private void DebugHookCallbackInternal (LuaCore.lua_State luaState, LuaCore.lua_Debug luaDebug) { try { var temp = DebugHook; if (!temp.IsNull ()) temp (this, new DebugHookEventArgs (luaDebug)); } catch (Exception ex) { OnHookException (new HookExceptionEventArgs (ex)); } }
/* * Gets the userdata in the index positon of the Lua stack. */ internal LuaUserData getUserData (LuaCore.lua_State luaState, int index) { LuaLib.lua_pushvalue (luaState, index); return new LuaUserData (LuaLib.lua_ref (luaState, 1), interpreter); }
/* * CAUTION: NLua.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 NLua.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); ObjectTranslatorPool.Instance.Add (luaState, translator); LuaLib.lua_replace (lState, (int)LuaIndexes.Globals); LuaLib.luaL_dostring (lState, Lua.init_luanet); // steffenj: lua_dostring renamed to luaL_dostring } _StatePassed = true; }
/* * Gets the function in the index positon of the Lua stack. */ internal LuaFunction getFunction (LuaCore.lua_State luaState, int index) { LuaLib.lua_pushvalue (luaState, index); return new LuaFunction (LuaLib.lua_ref (luaState, 1), interpreter); }
/// <summary> /// Sets local (see lua docs) /// </summary> /// <param name = "luaDebug">lua debug structure</param> /// <param name = "n">see lua docs</param> /// <returns>see lua docs</returns> /// <author>Reinhard Ostermeier</author> public string SetLocal (LuaCore.lua_Debug luaDebug, int n) { return LuaCore.lua_setlocal (luaState, luaDebug, n).ToString (); }
private int importTypeInternal (LuaCore.lua_State luaState) { string className = LuaLib.lua_tostring (luaState, 1).ToString (); var klass = FindType (className); if (!klass.IsNull ()) pushType (luaState, klass); else LuaLib.lua_pushnil (luaState); return 1; }