Пример #1
0
        /*
         * 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
                luaState.GetMetaTable(o.GetType().AssemblyQualifiedName);

                if (luaState.IsNil(-1))
                {
                    luaState.SetTop(-2);
                    luaState.NewMetaTable(o.GetType().AssemblyQualifiedName);
                    luaState.PushString("cache");
                    luaState.NewTable();
                    luaState.RawSet(-3);
                    luaState.PushLightUserData(_tagPtr);
                    luaState.PushNumber(1);
                    luaState.RawSet(-3);
                    luaState.PushString("__index");
                    luaState.PushString("luaNet_indexfunction");
                    luaState.RawGet(LuaRegistry.Index);
                    luaState.RawSet(-3);
                    luaState.PushString("__gc");
                    luaState.PushCFunction(MetaFunctions.GcFunction);
                    luaState.RawSet(-3);
                    luaState.PushString("__tostring");
                    luaState.PushCFunction(MetaFunctions.ToStringFunction);
                    luaState.RawSet(-3);
                    luaState.PushString("__concat");
                    luaState.PushCFunction(MetaFunctions.ConcatFunction);
                    luaState.RawSet(-3);
                    luaState.PushString("__newindex");
                    luaState.PushCFunction(MetaFunctions.NewIndexFunction);
                    luaState.RawSet(-3);
                    // Bind C# operator with Lua metamethods (__add, __sub, __mul)
                    RegisterOperatorsFunctions(luaState, o.GetType());
                    RegisterCallMethodForDelegate(luaState, o);
                }
            }
            else
            {
                luaState.GetMetaTable(metatable);
            }

            // Stores the object index in the Lua list and pushes the
            // index into the Lua stack
            luaState.GetMetaTable("luaNet_objects");
            luaState.NewUData(index);
            luaState.PushCopy(-3);
            luaState.Remove(-4);
            luaState.SetMetaTable(-2);
            luaState.PushCopy(-1);
            luaState.RawSetInteger(-3, index);
            luaState.Remove(-2);
        }
Пример #2
0
        private int UnregisterTableInternal(LuaState luaState)
        {
            if (!luaState.GetMetaTable(1))
            {
                ThrowError(luaState, "unregister_table: arg is not valid table");
                return(0);
            }

            luaState.PushString("__index");
            luaState.GetTable(-2);
            object obj = GetRawNetObject(luaState, -1);

            if (obj == null)
            {
                ThrowError(luaState, "unregister_table: arg is not valid table");
            }

            var luaTableField = obj.GetType().GetField("__luaInterface_luaTable");

            if (luaTableField == null)
            {
                ThrowError(luaState, "unregister_table: arg is not valid table");
            }

            // ReSharper disable once PossibleNullReferenceException
            luaTableField.SetValue(obj, null);
            luaState.PushNil();
            luaState.SetMetaTable(1);
            luaState.PushString("base");
            luaState.PushNil();
            luaState.SetTable(1);

            return(0);
        }
Пример #3
0
        public static IntPtr CheckUData(this LuaState state, int ud, string name)
        {
            IntPtr p = state.ToUserData(ud);

            if (p == IntPtr.Zero)
            {
                return(IntPtr.Zero);
            }
            if (!state.GetMetaTable(ud))
            {
                return(IntPtr.Zero);
            }

            state.GetField(LuaRegistry.Index, name);

            bool isEqual = state.RawEqual(-1, -2);

            state.Pop(2);

            if (isEqual)
            {
                return(p);
            }

            return(IntPtr.Zero);
        }
Пример #4
0
        public static bool CheckMetaTable(this LuaState state, int index, IntPtr tag)
        {
            if (!state.GetMetaTable(index))
            {
                return(false);
            }

            state.PushLightUserData(tag);
            state.RawGet(-2);
            bool isNotNil = !state.IsNil(-1);

            state.SetTop(-3);
            return(isNotNil);
        }
Пример #5
0
        private int UnregisterTableInternal(LuaState luaState)
        {
            try
            {
                if (luaState.GetMetaTable(1))
                {
                    luaState.PushString("__index");
                    luaState.GetTable(-2);
                    object obj = GetRawNetObject(luaState, -1);

                    if (obj == null)
                    {
                        ThrowError(luaState, "unregister_table: arg is not valid table");
                    }

                    var luaTableField = obj.GetType().GetField("__luaInterface_luaTable");

                    if (luaTableField == null)
                    {
                        ThrowError(luaState, "unregister_table: arg is not valid table");
                    }

                    luaTableField.SetValue(obj, null);
                    luaState.PushNil();
                    luaState.SetMetaTable(1);
                    luaState.PushString("base");
                    luaState.PushNil();
                    luaState.SetTable(1);
                }
                else
                {
                    ThrowError(luaState, "unregister_table: arg is not valid table");
                }
            }
            catch (Exception e)
            {
                ThrowError(luaState, e.Message);
            }

            return(0);
        }
Пример #6
0
        /*
         * 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)
            {
                luaState.PushNil();
                return;
            }

            // Object already in the list of Lua objects? Push the stored reference.
            bool found = (!o.GetType().IsValueType || o.GetType().IsEnum) && _objectsBackMap.TryGetValue(o, out index);

            if (found)
            {
                luaState.GetMetaTable("luaNet_objects");
                luaState.RawGetInteger(-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 = luaState.Type(-1);
                if (type != LuaType.Nil)
                {
                    luaState.Remove(-2);         // drop the metatable - we're going to leave our object on the stack
                    return;
                }

                // MetaFunctions.dumpStack(this, luaState);
                luaState.Remove(-1);     // remove the nil object value
                luaState.Remove(-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);
        }