Esempio n. 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);
        }
Esempio n. 2
0
        /*
         * __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);
        }
Esempio n. 3
0
        /*
         * __call metafunction of type references. Searches for and calls
         * a constructor for the type. Returns nil if the constructor is not
         * found or if the arguments are invalid. Throws an error if the constructor
         * generates an exception.
         */
        private int callConstructor(LuaCore.lua_State luaState)
        {
            var      validConstructor = new MethodCache();
            IReflect klass;
            object   obj = translator.getRawNetObject(luaState, 1);

            if (obj.IsNull() || !(obj is IReflect))
            {
                translator.throwError(luaState, "trying to call constructor on an invalid type reference");
                LuaLib.lua_pushnil(luaState);
                return(1);
            }
            else
            {
                klass = (IReflect)obj;
            }

            LuaLib.lua_remove(luaState, 1);
            var constructors = klass.UnderlyingSystemType.GetConstructors();

            foreach (var constructor in constructors)
            {
                bool isConstructor = matchParameters(luaState, constructor, ref validConstructor);

                if (isConstructor)
                {
                    try
                    {
                        translator.push(luaState, constructor.Invoke(validConstructor.args));
                    }
                    catch (TargetInvocationException e)
                    {
                        ThrowError(luaState, e);
                        LuaLib.lua_pushnil(luaState);
                    }
                    catch
                    {
                        LuaLib.lua_pushnil(luaState);
                    }

                    return(1);
                }
            }

            string constructorName = (constructors.Length == 0) ? "unknown" : constructors[0].Name;

            translator.throwError(luaState, String.Format("{0} does not contain constructor({1}) argument match",
                                                          klass.UnderlyingSystemType, constructorName));
            LuaLib.lua_pushnil(luaState);
            return(1);
        }
Esempio n. 4
0
 /*
  * 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");
     }
 }
Esempio n. 5
0
        /*
         * __tostring metafunction of CLR objects.
         */
        private int toString(LuaCore.lua_State luaState)
        {
            object obj = translator.getRawNetObject(luaState, 1);

            if (!obj.IsNull())
            {
                translator.push(luaState, obj.ToString() + ": " + obj.GetHashCode());
            }
            else
            {
                LuaLib.lua_pushnil(luaState);
            }

            return(1);
        }
Esempio n. 6
0
        /// <summary>
        /// Convert C# exceptions into Lua errors
        /// </summary>
        /// <returns>num of things on stack</returns>
        /// <param name = "e">null for no pending exception</param>
        internal int SetPendingException(Exception e)
        {
            var caughtExcept = e;

            if (!caughtExcept.IsNull())
            {
                translator.throwError(luaState, caughtExcept);
                LuaLib.lua_pushnil(luaState);
                return(1);
            }
            else
            {
                return(0);
            }
        }
Esempio n. 7
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);
        }
Esempio n. 8
0
        /*
         * Implementation of import_type. Returns nil if the
         * type is not found.
         */
        private int importType(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);
        }
Esempio n. 9
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);
        }
Esempio n. 10
0
        /*
         * Implementation of free_object. Clears the metatable and the
         * base field, freeing the created object for garbage-collection
         */
        private int unregisterTable(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);
        }
Esempio n. 11
0
        /*
         * 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);
        }
Esempio n. 12
0
        /*
         * __index metafunction of type references, works on static members.
         */
        private int getClassMethod(LuaCore.lua_State luaState)
        {
            IReflect klass;
            object   obj = translator.getRawNetObject(luaState, 1);

            if (obj.IsNull() || !(obj is IReflect))
            {
                translator.throwError(luaState, "trying to index an invalid type reference");
                LuaLib.lua_pushnil(luaState);
                return(1);
            }
            else
            {
                klass = (IReflect)obj;
            }

            if (LuaLib.lua_isnumber(luaState, 2))
            {
                int size = (int)LuaLib.lua_tonumber(luaState, 2);
                translator.push(luaState, Array.CreateInstance(klass.UnderlyingSystemType, size));
                return(1);
            }
            else
            {
                string methodName = LuaLib.lua_tostring(luaState, 2).ToString();

                if (methodName.IsNull())
                {
                    LuaLib.lua_pushnil(luaState);
                    return(1);
                }                 //CP: Ignore case
                else
                {
                    return(getMember(luaState, klass, null, methodName, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.IgnoreCase));
                }
            }
        }
Esempio n. 13
0
        /*
         * Pushes the value of a member or a delegate to call it, depending on the type of
         * the member. Works with static or instance members.
         * Uses reflection to find members, and stores the reflected MemberInfo object in
         * a cache (indexed by the type of the object and the name of the member).
         */
        private int getMember(LuaCore.lua_State luaState, IReflect objType, object obj, string methodName, BindingFlags bindingType)
        {
            bool       implicitStatic = false;
            MemberInfo member         = null;
            object     cachedMember   = checkMemberCache(memberCache, objType, methodName);

            //object cachedMember=null;

            if (cachedMember is LuaCore.lua_CFunction)
            {
                translator.pushFunction(luaState, (LuaCore.lua_CFunction)cachedMember);
                translator.push(luaState, true);
                return(2);
            }
            else if (!cachedMember.IsNull())
            {
                member = (MemberInfo)cachedMember;
            }
            else
            {
                //CP: Removed NonPublic binding search
                var members = objType.GetMember(methodName, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase /*| BindingFlags.NonPublic*/);

                if (members.Length > 0)
                {
                    member = members[0];
                }
                else
                {
                    // If we can't find any suitable instance members, try to find them as statics - but we only want to allow implicit static
                    // lookups for fields/properties/events -kevinh
                    //CP: Removed NonPublic binding search and made case insensitive
                    members = objType.GetMember(methodName, bindingType | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase /*| BindingFlags.NonPublic*/);

                    if (members.Length > 0)
                    {
                        member         = members[0];
                        implicitStatic = true;
                    }
                }
            }

            if (!member.IsNull())
            {
                if (member.MemberType == MemberTypes.Field)
                {
                    var field = (FieldInfo)member;

                    if (cachedMember.IsNull())
                    {
                        setMemberCache(memberCache, objType, methodName, member);
                    }

                    try
                    {
                        translator.push(luaState, field.GetValue(obj));
                    }
                    catch
                    {
                        LuaLib.lua_pushnil(luaState);
                    }
                }
                else if (member.MemberType == MemberTypes.Property)
                {
                    var property = (PropertyInfo)member;
                    if (cachedMember.IsNull())
                    {
                        setMemberCache(memberCache, objType, methodName, member);
                    }

                    try
                    {
                        object val = property.GetValue(obj, null);
                        translator.push(luaState, val);
                    }
                    catch (ArgumentException)
                    {
                        // If we can't find the getter in our class, recurse up to the base class and see
                        // if they can help.
                        if (objType is Type && !(((Type)objType) == typeof(object)))
                        {
                            return(getMember(luaState, ((Type)objType).BaseType, obj, methodName, bindingType));
                        }
                        else
                        {
                            LuaLib.lua_pushnil(luaState);
                        }
                    }
                    catch (TargetInvocationException e)                     // Convert this exception into a Lua error
                    {
                        ThrowError(luaState, e);
                        LuaLib.lua_pushnil(luaState);
                    }
                }
                else if (member.MemberType == MemberTypes.Event)
                {
                    var eventInfo = (EventInfo)member;
                    if (cachedMember.IsNull())
                    {
                        setMemberCache(memberCache, objType, methodName, member);
                    }

                    translator.push(luaState, new RegisterEventHandler(translator.pendingEvents, obj, eventInfo));
                }
                else if (!implicitStatic)
                {
                    if (member.MemberType == MemberTypes.NestedType)
                    {
                        // kevinh - added support for finding nested types
                        // cache us
                        if (cachedMember.IsNull())
                        {
                            setMemberCache(memberCache, objType, methodName, member);
                        }

                        // Find the name of our class
                        string name    = member.Name;
                        var    dectype = member.DeclaringType;

                        // Build a new long name and try to find the type by name
                        string longname   = dectype.FullName + "+" + name;
                        var    nestedType = translator.FindType(longname);
                        translator.pushType(luaState, nestedType);
                    }
                    else
                    {
                        // Member type must be 'method'
                        var wrapper = new LuaCore.lua_CFunction((new LuaMethodWrapper(translator, objType, methodName, bindingType)).call);

                        if (cachedMember.IsNull())
                        {
                            setMemberCache(memberCache, objType, methodName, wrapper);
                        }

                        translator.pushFunction(luaState, wrapper);
                        translator.push(luaState, true);
                        return(2);
                    }
                }
                else
                {
                    // If we reach this point we found a static method, but can't use it in this context because the user passed in an instance
                    translator.throwError(luaState, "can't pass instance to static method " + methodName);
                    LuaLib.lua_pushnil(luaState);
                }
            }
            else
            {
                // kevinh - we want to throw an exception because meerly returning 'nil' in this case
                // is not sufficient.  valid data members may return nil and therefore there must be some
                // way to know the member just doesn't exist.
                translator.throwError(luaState, "unknown member name " + methodName);
                LuaLib.lua_pushnil(luaState);
            }

            // push false because we are NOT returning a function (see luaIndexFunction)
            translator.push(luaState, false);
            return(2);
        }
Esempio n. 14
0
        /*
         * 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);
        }