/// <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)); }