예제 #1
0
        /*
         * Implementation of get_constructor_bysig. Returns nil
         * if no matching constructor is found.
         */
        private int getConstructorSignature(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)).call));
            }
            catch (Exception e)
            {
                throwError(luaState, e);
                LuaLib.lua_pushnil(luaState);
            }

            return(1);
        }
예제 #2
0
        /*
         * 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);
        }
예제 #3
0
        /*
         * 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 ArrayList();

                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());
            }
        }
예제 #4
0
        /*
         * Excutes a Lua file and returns all the chunk's return
         * values in an array
         */
        public object[] DoFile(string fileName)
        {
            int oldTop = LuaLib.lua_gettop(luaState);

            if (LuaLib.luaL_loadfile(luaState, fileName) == 0)
            {
                executing = true;

                try
                {
                    if (LuaLib.lua_pcall(luaState, 0, -1, 0) == 0)
                    {
                        return(translator.popValues(luaState, oldTop));
                    }
                    else
                    {
                        ThrowExceptionFromError(oldTop);
                    }
                }
                finally
                {
                    executing = false;
                }
            }
            else
            {
                ThrowExceptionFromError(oldTop);
            }

            return(null);                               // Never reached - keeps compiler happy
        }
예제 #5
0
        /*
         * Sets a field of the table or userdata corresponding the the provided reference
         * to the provided value
         */
        internal void setObject(int reference, string field, object val)
        {
            int oldTop = LuaLib.lua_gettop(luaState);

            LuaLib.lua_getref(luaState, reference);
            setObject(field.Split(new char[] { '.' }), val);
            LuaLib.lua_settop(luaState, oldTop);
        }
예제 #6
0
        /*
         * Indexer for global variables from the LuaInterpreter
         * Supports navigation of tables by using . operator
         */
        public object this[string fullPath]
        {
            get
            {
                object   returnValue = null;
                int      oldTop      = LuaLib.lua_gettop(luaState);
                string[] path        = fullPath.Split(new char[] { '.' });
                LuaLib.lua_getglobal(luaState, path[0]);
                returnValue = translator.getObject(luaState, -1);

                if (path.Length > 1)
                {
                    string[] remainingPath = new string[path.Length - 1];
                    Array.Copy(path, 1, remainingPath, 0, path.Length - 1);
                    returnValue = getObject(remainingPath);
                }

                LuaLib.lua_settop(luaState, oldTop);
                return(returnValue);
            }
            set
            {
                int      oldTop = LuaLib.lua_gettop(luaState);
                string[] path   = fullPath.Split(new char[] { '.' });

                if (path.Length == 1)
                {
                    translator.push(luaState, value);
                    LuaLib.lua_setglobal(luaState, fullPath);
                }
                else
                {
                    LuaLib.lua_getglobal(luaState, path[0]);
                    string[] remainingPath = new string[path.Length - 1];
                    Array.Copy(path, 1, remainingPath, 0, path.Length - 1);
                    setObject(remainingPath, value);
                }

                LuaLib.lua_settop(luaState, oldTop);

                // Globals auto-complete
                if (value.IsNull())
                {
                    // Remove now obsolete entries
                    globals.Remove(fullPath);
                }
                else
                {
                    // Add new entries
                    if (!globals.Contains(fullPath))
                    {
                        registerGlobal(fullPath, value.GetType(), 0);
                    }
                }
            }
        }
예제 #7
0
        /*
         * Sets a numeric field of the table or userdata corresponding the the provided reference
         * to the provided value
         */
        internal void setObject(int reference, object field, object val)
        {
            int oldTop = LuaLib.lua_gettop(luaState);

            LuaLib.lua_getref(luaState, reference);
            translator.push(luaState, field);
            translator.push(luaState, val);
            LuaLib.lua_settable(luaState, -3);
            LuaLib.lua_settop(luaState, oldTop);
        }
예제 #8
0
        /*
         * Gets a field of the table or userdata corresponding to the provided reference
         */
        internal object getObject(int reference, string field)
        {
            int oldTop = LuaLib.lua_gettop(luaState);

            LuaLib.lua_getref(luaState, reference);
            object returnValue = getObject(field.Split(new char[] { '.' }));

            LuaLib.lua_settop(luaState, oldTop);
            return(returnValue);
        }
예제 #9
0
        /*
         * Compares the two values referenced by ref1 and ref2 for equality
         */
        internal bool compareRef(int ref1, int ref2)
        {
            int top = LuaLib.lua_gettop(luaState);

            LuaLib.lua_getref(luaState, ref1);
            LuaLib.lua_getref(luaState, ref2);
            int equal = LuaLib.lua_equal(luaState, -1, -2);

            LuaLib.lua_settop(luaState, top);
            return(equal != 0);
        }
예제 #10
0
        /*
         * Gets a numeric field of the table or userdata corresponding the the provided reference
         */

        internal object getObject(int reference, object field)
        {
            int oldTop = LuaLib.lua_gettop(luaState);

            LuaLib.lua_getref(luaState, reference);
            translator.push(luaState, field);
            LuaLib.lua_gettable(luaState, -2);
            object returnValue = translator.getObject(luaState, -1);

            LuaLib.lua_settop(luaState, oldTop);
            return(returnValue);
        }
예제 #11
0
        /*
         * 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);
        }
예제 #12
0
        /*
         * Registers an object's method as a Lua function (global or table field)
         * The method may have any signature
         */
        public LuaFunction RegisterFunction(string path, object target, MethodBase function /*MethodInfo function*/)          //CP: Fix for struct constructor by Alexander Kappner (link: http://luaforge.net/forum/forum.php?thread_id = 2859&forum_id = 145)
        {
            // We leave nothing on the stack when we are done
            int oldTop  = LuaLib.lua_gettop(luaState);
            var wrapper = new LuaMethodWrapper(translator, target, function.DeclaringType, function);

            translator.push(luaState, new LuaCore.lua_CFunction(wrapper.call));
            this[path] = translator.getObject(luaState, -1);
            var f = GetFunction(path);

            LuaLib.lua_settop(luaState, oldTop);
            return(f);
        }
예제 #13
0
        /// <summary>
        ///
        /// </summary>
        /// <param name = "fileName"></param>
        /// <returns></returns>
        public LuaFunction LoadFile(string fileName)
        {
            int oldTop = LuaLib.lua_gettop(luaState);

            if (LuaLib.luaL_loadfile(luaState, fileName) != 0)
            {
                ThrowExceptionFromError(oldTop);
            }

            var result = translator.getFunction(luaState, -1);

            translator.popValues(luaState, oldTop);
            return(result);
        }
예제 #14
0
        /*
         * Implementation of get_method_bysig. Returns nil
         * if no matching method is not found.
         */
        private int getMethodSignature(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)).call));
            }
            catch (Exception e)
            {
                throwError(luaState, e);
                LuaLib.lua_pushnil(luaState);
            }

            return(1);
        }
예제 #15
0
        public ListDictionary GetTableDict(LuaTable table)
        {
            var dict   = new ListDictionary();
            int oldTop = LuaLib.lua_gettop(luaState);

            translator.push(luaState, table);
            LuaLib.lua_pushnil(luaState);

            while (LuaLib.lua_next(luaState, -2) != 0)
            {
                dict[translator.getObject(luaState, -2)] = translator.getObject(luaState, -1);
                LuaLib.lua_settop(luaState, -2);
            }

            LuaLib.lua_settop(luaState, oldTop);
            return(dict);
        }
예제 #16
0
        /// <summary>
        /// Debug tool to dump the lua stack
        /// </summary>
        /// FIXME, move somewhere else
        public static void dumpStack(ObjectTranslator translator, LuaCore.lua_State luaState)
        {
            int depth = LuaLib.lua_gettop(luaState);

            Debug.WriteLine("lua stack depth: " + depth);

            for (int i = 1; i <= depth; i++)
            {
                var type = LuaLib.lua_type(luaState, i);
                // we dump stacks when deep in calls, calling typename while the stack is in flux can fail sometimes, so manually check for key types
                string typestr = (type == LuaTypes.Table) ? "table" : LuaLib.lua_typename(luaState, type);
                string strrep  = LuaLib.lua_tostring(luaState, i).ToString();

                if (type == LuaTypes.UserData)
                {
                    object obj = translator.getRawNetObject(luaState, i);
                    strrep = obj.ToString();
                }
            }
        }
예제 #17
0
        /*
         * 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 ArrayList();
                for (int i = oldTop + 1; i <= newTop; i++)
                {
                    returnValues.Add(getObject(luaState, i));
                }

                LuaLib.lua_settop(luaState, oldTop);
                return(returnValues.ToArray());
            }
        }
예제 #18
0
        /*
         * Calls the object as a function with the provided arguments and
         * casting returned values to the types in returnTypes before returning
         * them in an array
         */
        internal object[] callFunction(object function, object[] args, Type[] returnTypes)
        {
            int nArgs  = 0;
            int oldTop = LuaLib.lua_gettop(luaState);

            if (!LuaLib.lua_checkstack(luaState, args.Length + 6))
            {
                throw new LuaException("Lua stack overflow");
            }

            translator.push(luaState, function);

            if (!args.IsNull())
            {
                nArgs = args.Length;

                for (int i = 0; i < args.Length; i++)
                {
                    translator.push(luaState, args[i]);
                }
            }

            executing = true;

            try
            {
                int error = LuaLib.lua_pcall(luaState, nArgs, -1, 0);
                if (error != 0)
                {
                    ThrowExceptionFromError(oldTop);
                }
            }
            finally
            {
                executing = false;
            }

            return(!returnTypes.IsNull() ? translator.popValues(luaState, oldTop, returnTypes) : translator.popValues(luaState, oldTop));
        }
예제 #19
0
        /*
         * Passes errors (argument e) to the Lua interpreter
         */
        internal void throwError(LuaCore.lua_State luaState, object e)
        {
            // We use this to remove anything pushed by luaL_where
            int oldTop = LuaLib.lua_gettop(luaState);

            // Stack frame #1 is our C# wrapper, so not very interesting to the user
            // Stack frame #2 must be the lua code that called us, so that's what we want to use
            LuaLib.luaL_where(luaState, 1);
            var curlev = popValues(luaState, oldTop);

            // Determine the position in the script where the exception was triggered
            string errLocation = string.Empty;

            if (curlev.Length > 0)
            {
                errLocation = curlev[0].ToString();
            }

            string message = e as string;

            if (!message.IsNull())
            {
                // Wrap Lua error (just a string) and store the error location
                e = new LuaScriptException(message, errLocation);
            }
            else
            {
                var ex = e as Exception;

                if (!ex.IsNull())
                {
                    // Wrap generic .NET exception as an InnerException and store the error location
                    e = new LuaScriptException(ex, errLocation);
                }
            }

            push(luaState, e);
            LuaLib.lua_error(luaState);
        }
예제 #20
0
        /// <summary>
        ///
        /// </summary>
        /// <param name = "chunk"></param>
        /// <param name = "name"></param>
        /// <returns></returns>
        public LuaFunction LoadString(string chunk, string name)
        {
            int oldTop = LuaLib.lua_gettop(luaState);

            executing = true;

            try
            {
                if (LuaLib.luaL_loadbuffer(luaState, chunk, name) != 0)
                {
                    ThrowExceptionFromError(oldTop);
                }
            }
            finally
            {
                executing = false;
            }

            var result = translator.getFunction(luaState, -1);

            translator.popValues(luaState, oldTop);
            return(result);
        }
예제 #21
0
        /*
         * Matches a method against its arguments in the Lua stack. Returns
         * if the match was succesful. It it was also returns the information
         * necessary to invoke the method.
         */
        internal bool matchParameters(LuaCore.lua_State luaState, MethodBase method, ref MethodCache methodCache)
        {
            ExtractValue extractValue;
            bool         isMethod        = true;
            var          paramInfo       = method.GetParameters();
            int          currentLuaParam = 1;
            int          nLuaParams      = LuaLib.lua_gettop(luaState);
            var          paramList       = new ArrayList();
            var          outList         = new List <int>();
            var          argTypes        = new List <MethodArgs>();

            foreach (var currentNetParam in paramInfo)
            {
                if (!currentNetParam.IsIn && currentNetParam.IsOut)                 // Skips out params
                {
                    outList.Add(paramList.Add(null));
                }
                else if (currentLuaParam > nLuaParams)                // Adds optional parameters
                {
                    if (currentNetParam.IsOptional)
                    {
                        paramList.Add(currentNetParam.DefaultValue);
                    }
                    else
                    {
                        isMethod = false;
                        break;
                    }
                }
                else if (_IsTypeCorrect(luaState, currentLuaParam, currentNetParam, out extractValue))                 // Type checking
                {
                    int index     = paramList.Add(extractValue(luaState, currentLuaParam));
                    var methodArg = new MethodArgs();
                    methodArg.index        = index;
                    methodArg.extractValue = extractValue;
                    argTypes.Add(methodArg);

                    if (currentNetParam.ParameterType.IsByRef)
                    {
                        outList.Add(index);
                    }

                    currentLuaParam++;
                }                  // Type does not match, ignore if the parameter is optional
                else if (_IsParamsArray(luaState, currentLuaParam, currentNetParam, out extractValue))
                {
                    object luaParamValue  = extractValue(luaState, currentLuaParam);
                    var    paramArrayType = currentNetParam.ParameterType.GetElementType();
                    Array  paramArray;

                    if (luaParamValue is LuaTable)
                    {
                        var table           = (LuaTable)luaParamValue;
                        var tableEnumerator = table.GetEnumerator();
                        paramArray = Array.CreateInstance(paramArrayType, table.Values.Count);
                        tableEnumerator.Reset();
                        int paramArrayIndex = 0;

                        while (tableEnumerator.MoveNext())
                        {
                            paramArray.SetValue(Convert.ChangeType(tableEnumerator.Value, currentNetParam.ParameterType.GetElementType()), paramArrayIndex);
                            paramArrayIndex++;
                        }
                    }
                    else
                    {
                        paramArray = Array.CreateInstance(paramArrayType, 1);
                        paramArray.SetValue(luaParamValue, 0);
                    }

                    int index     = paramList.Add(paramArray);
                    var methodArg = new MethodArgs();
                    methodArg.index           = index;
                    methodArg.extractValue    = extractValue;
                    methodArg.isParamsArray   = true;
                    methodArg.paramsArrayType = paramArrayType;
                    argTypes.Add(methodArg);
                    currentLuaParam++;
                }
                else if (currentNetParam.IsOptional)
                {
                    paramList.Add(currentNetParam.DefaultValue);
                }
                else                  // No match
                {
                    isMethod = false;
                    break;
                }
            }

            if (currentLuaParam != nLuaParams + 1)            // Number of parameters does not match
            {
                isMethod = false;
            }
            if (isMethod)
            {
                methodCache.args         = paramList.ToArray();
                methodCache.cachedMethod = method;
                methodCache.outList      = outList.ToArray();
                methodCache.argTypes     = argTypes.ToArray();
            }

            return(isMethod);
        }
예제 #22
0
        /// <summary>
        /// Pops a value from the lua stack.
        /// </summary>
        /// <returns>Returns the top value from the lua stack.</returns>
        /// <author>Reinhard Ostermeier</author>
        public object Pop()
        {
            int top = LuaLib.lua_gettop(luaState);

            return(translator.popValues(luaState, top - 1)[0]);
        }