Exemplo n.º 1
0
        private int pushFunctionLut(System.Reflection.MethodInfo mi, string bindName)
        {
            int top = LuaDll.lua_gettop(L);

            // Push global lut to the stack
            string globalLutName = "__Lua.cs__LUT__";

            LuaDll.lua_getfield(L, LuaDll.LUA_REGISTRYINDEX, globalLutName);
            if (LuaDll.lua_isnil(L, -1))
            {
                // If the global lut does not exist then create it and push it onto the stack.

                // Pop the nil value
                LuaDll.lua_pop(L, 1);

                // Push a new table and set it as the global globalLutName
                LuaDll.lua_newtable(L);
                LuaDll.lua_pushvalue(L, -1);    // Dupe for setglobal call.
                LuaDll.lua_setfield(L, LuaDll.LUA_REGISTRYINDEX, globalLutName);
            }
            int lut = LuaDll.lua_gettop(L);

            Debug.Assert(lut == (top + 1));

            // Push function lut to the stack.
            string fullName = mi.ReflectedType.FullName + "." + bindName;

            LuaDll.lua_getfield(L, lut, fullName);

            if (LuaDll.lua_isnil(L, -1))
            {
                // If the function lut does not exist then create it.

                // Pop off the nil result.
                LuaDll.lua_pop(L, 1);

                // Push in a new table
                LuaDll.lua_newtable(L);

                // Add the name to the table as kFunctionNameKey
                LuaDll.lua_pushstring(L, bindName);
                LuaDll.lua_setfield(L, -2, kFunctionNameKey);

                // Add this to the global lut, keyed on FullName
                LuaDll.lua_pushvalue(L, -1);
                LuaDll.lua_setfield(L, lut, fullName);
            }

            // Remove the global lut
            LuaDll.lua_remove(L, lut);

            // Now we have the function lut at the top of the stack.
            int result = LuaDll.lua_gettop(L);

            Debug.Assert(result == top + 1);

            // Return the stack position of the lut.
            return(result);
        }
Exemplo n.º 2
0
        private void pushFunction(System.Reflection.MethodInfo mi, string bindName)
        {
            int top = LuaDll.lua_gettop(L);

            // Generate unique name based on parameter list.
            string mangle = buildMangledNameFromMethodInfo(mi, bindName);

            // Push the Look Up Table for this function onto the Lua stack.
            int flut = pushFunctionLut(mi, bindName);

            // Lookup the manged name.
            LuaDll.lua_getfield(L, flut, mangle);

            // If not already defined then go ahead and define it
            if (LuaDll.lua_isnil(L, -1))
            {
                // Pop nil value
                LuaDll.lua_pop(L, 1);

                // Store the function in a GCHandle in a global list so it
                // doesn't get garbage collected.
                GCHandle h = GCHandle.Alloc(mi);
                mLuaReferences.Add(h);

                // functionLut[mangledName] = MethodInfo
                LuaDll.lua_pushlightuserdata(L, GCHandle.ToIntPtr(h));
                LuaDll.lua_setfield(L, flut, mangle);

                // Push the function call delegate with the function lut as an up value.
                LuaDll.lua_pushcclosure(L, mLuaFunctionCallAdapterDelegate, 1);
            }
            else
            {
                System.Reflection.MethodInfo oldMi = (System.Reflection.MethodInfo)GCHandle.FromIntPtr(LuaDll.lua_touserdata(L, -1)).Target;
                throw new Exception(String.Format("Duplicate function registration of '{0}', old={1}, new={2}", demangleName(mangle), oldMi, mi));
            }

            Debug.Assert(LuaDll.lua_gettop(L) == top + 1);
        }
Exemplo n.º 3
0
        public MultiValue call(string func, params object[] args)
        {
            int top = LuaDll.lua_gettop(L);

            MultiValue mv = new MultiValue(args);

            LuaDll.lua_getfield(L, LuaDll.LUA_GLOBALSINDEX, func);
            int count = pushValue(mv);
            int ret   = LuaDll.lua_pcall(L, count, LuaDll.LUA_MULTRET, 0);

            if (ret != 0)
            {
                string err = LuaDll.lua_tostring(L, -1);
                Console.WriteLine("ERROR: " + err);
                LuaDll.lua_pop(L, 1);
            }
            else
            {
                int newtop = LuaDll.lua_gettop(L);
                return(getValues(top + 1, newtop - top));
            }

            return(null);
        }
Exemplo n.º 4
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));
        }