Пример #1
0
        internal void PushObject(object obj, IntPtr?stateOverride = null)
        {
            var state = stateOverride ?? MainState;

            Debug.Assert(LuaApi.GetMainState(state) == MainState, "State override did not match main state.");

            if (obj == null)
            {
                LuaApi.PushNil(state);
                return;
            }

            if (obj is IConvertible conv)
            {
                switch (conv.GetTypeCode())
                {
                case TypeCode.Boolean:
                    LuaApi.PushBoolean(state, (bool)obj);
                    return;

                case TypeCode.SByte:
                case TypeCode.Byte:
                case TypeCode.Int16:
                case TypeCode.UInt16:
                case TypeCode.Int32:
                case TypeCode.UInt32:
                case TypeCode.Int64:
                    LuaApi.PushInteger(state, conv.ToInt64(null));
                    return;

                case TypeCode.UInt64:
                    LuaApi.PushInteger(state, (long)((ulong)conv));
                    return;

                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                    LuaApi.PushNumber(state, conv.ToDouble(null));
                    return;

                case TypeCode.Char:
                case TypeCode.String:
                    LuaApi.PushString(state, conv.ToString());
                    return;

                default:
                    ObjectBinder.PushNetObject(state, conv);
                    return;
                }
            }
            else if (obj is LuaReference luaReference)
            {
                luaReference.PushOnto(state);
            }
            else
            {
                ObjectBinder.PushNetObject(state, obj);
            }
        }
Пример #2
0
        internal void PushOnto(IntPtr state)
        {
            if (state != Lua.MainState && LuaApi.GetMainState(state) != Lua.MainState)
            {
                throw new ArgumentException("Reference cannot be pushed onto the given Lua environment.", nameof(state));
            }

            LuaApi.RawGetI(state, LuaApi.RegistryIndex, _referenceId);
        }
Пример #3
0
        internal object[] Call(object[] args, IntPtr?stateOverride = null, bool isResuming = false)
        {
            var state = stateOverride ?? MainState;

            Debug.Assert(LuaApi.GetMainState(state) == MainState, "State override did not match main state.");
            Debug.Assert(isResuming || LuaApi.Type(state, -1) == LuaType.Function, "Stack doesn't have function on top.");

            var oldTop  = isResuming ? 0 : LuaApi.GetTop(state) - 1;
            var numArgs = args.Length;

            if (oldTop + numArgs > LuaApi.MinStackSize && !LuaApi.CheckStack(state, numArgs))
            {
                throw new LuaException("Not enough stack space for arguments.");
            }

            foreach (var arg in args)
            {
                PushObject(arg, state);
            }

            var status = isResuming ? LuaApi.Resume(state, MainState, numArgs) : LuaApi.PCallK(state, numArgs);

            if (status != LuaStatus.Ok && status != LuaStatus.Yield)
            {
                var errorMessage = LuaApi.ToString(state, -1);
                LuaApi.Pop(state, 1);
                throw new LuaException(errorMessage);
            }

            // This is a fast path for functions returning nothing since we avoid a SetTop call.
            var top = LuaApi.GetTop(state);

            if (top == oldTop)
            {
                return(EmptyObjectArray);
            }

            if (top + 1 > LuaApi.MinStackSize && !LuaApi.CheckStack(state, 1))
            {
                throw new LuaException("Not enough scratch stack space.");
            }

            var results = ToObjects(oldTop + 1, top, state);

            LuaApi.SetTop(state, oldTop);
            return(results);
        }
Пример #4
0
        internal object ToObject(int index, LuaType?typeHint = null, IntPtr?stateOverride = null)
        {
            var state = stateOverride ?? MainState;

            Debug.Assert(LuaApi.GetMainState(state) == MainState, "State override did not match main state.");
            var type = typeHint ?? LuaApi.Type(state, index);

            Debug.Assert(type == LuaApi.Type(state, index), "Type hint did not match type.");

            switch (type)
            {
            case LuaType.None:
            case LuaType.Nil:
                return(null);

            case LuaType.Boolean:
                return(LuaApi.ToBoolean(state, index));

            case LuaType.Number:
                var isInteger = LuaApi.IsInteger(state, index);
                return(isInteger ? LuaApi.ToInteger(state, index) : (object)LuaApi.ToNumber(state, index));

            case LuaType.String:
                return(LuaApi.ToString(state, index));

            case LuaType.Userdata:
                var handle = LuaApi.ToHandle(state, index);
                return(handle.Target);
            }

            LuaReference luaReference = null;
            var          pointer      = LuaApi.ToPointer(state, index);

            if (_cachedLuaReferences.TryGetValue(pointer, out var weakReference))
            {
                luaReference = (LuaReference)weakReference.Target;
                if (luaReference != null)
                {
                    return(luaReference);
                }
            }

            LuaApi.PushValue(state, index);
            var referenceId = LuaApi.Ref(state, LuaApi.RegistryIndex);

            switch (type)
            {
            case LuaType.Table:
                luaReference = new LuaTable(this, referenceId);
                break;

            case LuaType.Function:
                luaReference = new LuaFunction(this, referenceId);
                break;

            case LuaType.Thread:
                luaReference = new LuaThread(this, referenceId, pointer);
                break;
            }

            if (weakReference != null)
            {
                weakReference.Target = luaReference;
            }
            else
            {
                _cachedLuaReferences[pointer] = new WeakReference(luaReference);
            }
            _pointerToReferenceId[pointer] = referenceId;
            return(luaReference);
        }