Exemplo n.º 1
0
        /// <summary>
        /// Single lua function used for all C# function or method calls from lua.
        /// </summary>
        /// <param name="L">Lua state</param>
        /// <returns>Returns number of results pushed onto the stack</returns>
        private int functionCallAdapter(lua_State L)
        {
            // Figure out which function to call.
            // Our upvalue is a table of all methods with the same name as this one.

            // Get the function name.
            LuaDll.lua_getfield(L, LuaDll.lua_upvalueindex(1), kFunctionNameKey);
            string simpleName = LuaDll.lua_tostring(L, -1);

            LuaDll.lua_pop(L, 1);

            // Lookup the mangled name from the lut stored at upvalueindex.
            string mangledName = buildMangledNameFromLuaParameters(simpleName);

            LuaDll.lua_getfield(L, LuaDll.lua_upvalueindex(1), mangledName);

            if (LuaDll.lua_isnil(L, -1))
            {
                LuaDll.luaL_error(L, "Unknown function " + mangledName + " \"" + demangleName(mangledName) + "\"");
                return(0);
            }

            // Get the function delegate from the stack.
            GCHandle h = GCHandle.FromIntPtr(LuaDll.lua_topointer(L, -1));

            LuaDll.lua_pop(L, 1);

            System.Reflection.MethodInfo      fd    = (System.Reflection.MethodInfo)h.Target;
            System.Reflection.ParameterInfo[] pinfo = fd.GetParameters();
            int    firstParam = 0;
            Object self       = null;

            // Check if this is a static method or not.  If it is not static, then the first
            // parameter must be an instance of the class.
            if (!fd.IsStatic)
            {
                // Get the pointer to the object (and verify the type).
                IntPtr ud = LuaDll.luaL_checkudata(L, 1, fd.ReflectedType.FullName);

                // Copy the address of the object from the userdata.
                GCHandle hSelf = GCHandle.FromIntPtr(Marshal.ReadIntPtr(ud));

                // Since this is a non-static method, it will have an extra parameter.
                firstParam = 1;
                self       = hSelf.Target;
            }

            // Verify that we are getting the correct number of parameters
            if (pinfo.Length != (LuaDll.lua_gettop(L) - firstParam))
            {
                LuaDll.luaL_error(L, "Invalid number of parameters for function '{0}'", fd.Name);
                return(1);
            }

            Object[] parms         = new Object[pinfo.Length];
            int      firstLuaParam = firstParam + 1;

            for (int i = 0; i < pinfo.Length; ++i)
            {
                if (pinfo[i].ParameterType == typeof(int))
                {
                    parms[i] = LuaDll.luaL_checkinteger(L, i + firstLuaParam);
                }
                else if (pinfo[i].ParameterType == typeof(double))
                {
                    parms[i] = LuaDll.luaL_checknumber(L, i + firstLuaParam);
                }
                else if (pinfo[i].ParameterType == typeof(string))
                {
                    parms[i] = LuaDll.luaL_checkstring(L, i + firstLuaParam);
                }
                else if (pinfo[i].ParameterType == typeof(bool))
                {
                    LuaDll.luaL_checktype(L, i + firstLuaParam, LuaDll.LUA_TBOOLEAN);
                    parms[i] = LuaDll.lua_toboolean(L, i + firstLuaParam);
                }
                else
                {
                    // Get the pointer to the object.
                    IntPtr ud = LuaDll.lua_touserdata(L, i + firstLuaParam);
                    parms[i] = GCHandle.FromIntPtr(Marshal.ReadIntPtr(ud)).Target;
                }
            }
            object result = fd.Invoke(self, parms);

            return(pushValue(result));
        }