internal object[] Call(object[] args, IntPtr?stateOverride = null, bool isResuming = false) { var state = stateOverride ?? MainState; Debug.Assert(LuaApi.GetMainState(state) == MainState, "State override did not match main state."); Debug.Assert(isResuming || LuaApi.Type(state, -1) == LuaType.Function, "Stack doesn't have function on top."); var oldTop = isResuming ? 0 : LuaApi.GetTop(state) - 1; var numArgs = args.Length; if (oldTop + numArgs > LuaApi.MinStackSize && !LuaApi.CheckStack(state, numArgs)) { throw new LuaException("Not enough stack space for arguments."); } foreach (var arg in args) { PushObject(arg, state); } var status = isResuming ? LuaApi.Resume(state, MainState, numArgs) : LuaApi.PCallK(state, numArgs); if (status != LuaStatus.Ok && status != LuaStatus.Yield) { var errorMessage = LuaApi.ToString(state, -1); LuaApi.Pop(state, 1); throw new LuaException(errorMessage); } // This is a fast path for functions returning nothing since we avoid a SetTop call. var top = LuaApi.GetTop(state); if (top == oldTop) { return(EmptyObjectArray); } if (top + 1 > LuaApi.MinStackSize && !LuaApi.CheckStack(state, 1)) { throw new LuaException("Not enough scratch stack space."); } var results = ToObjects(oldTop + 1, top, state); LuaApi.SetTop(state, oldTop); return(results); }
private static int WrappedCall(IntPtr state, Func <int> function) { var oldTop = LuaApi.GetTop(state); try { LuaApi.PushBoolean(state, true); return(function() + 1); } catch (Exception e) { // If an exception occurs, then we need to reset the top. We don't know what state the stack is in! LuaApi.SetTop(state, oldTop); LuaApi.PushBoolean(state, false); if (e is LuaException) { LuaApi.PushString(state, e.Message); } else { LuaApi.PushString(state, $"unhandled .NET exception:\n{e}"); } return(2); } }