/// <summary> /// /// </summary> /// <param name = "chunk"></param> /// <param name = "name"></param> /// <returns></returns> public LuaFunction LoadString(byte[] chunk, string name) { int oldTop = LuaLib.LuaGetTop(luaState); executing = true; try { if (LuaLib.LuaLLoadBuffer(luaState, chunk, name) != 0) { ThrowExceptionFromError(oldTop); } } finally { executing = false; } var result = translator.GetFunction(luaState, -1); translator.PopValues(luaState, oldTop); return(result); }
/* * Gets the values from the provided index to * the top of the stack and returns them in an array. */ internal object[] PopValues(LuaState luaState, int oldTop) { int newTop = LuaLib.LuaGetTop(luaState); if (oldTop == newTop) { return(null); } else { var returnValues = new List <object> (); for (int i = oldTop + 1; i <= newTop; i++) { returnValues.Add(GetObject(luaState, i)); } LuaLib.LuaSetTop(luaState, oldTop); return(returnValues.ToArray()); } }
/* * Passes errors (argument e) to the Lua interpreter */ internal void ThrowError(LuaState luaState, object e) { // We use this to remove anything pushed by luaL_where int oldTop = LuaLib.LuaGetTop(luaState); // Stack frame #1 is our C# wrapper, so not very interesting to the user // Stack frame #2 must be the lua code that called us, so that's what we want to use LuaLib.LuaLWhere(luaState, 1); var curlev = PopValues(luaState, oldTop); // Determine the position in the script where the exception was triggered string errLocation = string.Empty; if (curlev.Length > 0) { errLocation = curlev [0].ToString(); } string message = e as string; if (message != null) { // Wrap Lua error (just a string) and store the error location e = new LuaScriptException(message, errLocation); } else { var ex = e as Exception; if (ex != null) { // Wrap generic .NET exception as an InnerException and store the error location e = new LuaScriptException(ex, errLocation); } } Push(luaState, e); LuaLib.LuaError(luaState); }
/// <summary> /// Executes a Lua chunk and returns all the chunk's return values in an array. /// </summary> /// <param name = "chunk">Chunk to execute</param> /// <param name = "chunkName">Name to associate with the chunk. Defaults to "chunk".</param> /// <returns></returns> public object[] DoString(string chunk, string chunkName = "chunk") { int oldTop = LuaLib.LuaGetTop(luaState); executing = true; if (LuaLib.LuaLLoadBuffer(luaState, chunk, chunkName) == 0) { int errfunction = 0; if (UseTraceback) { errfunction = PushDebugTraceback(luaState, 0); oldTop++; } try { if (LuaLib.LuaPCall(luaState, 0, -1, errfunction) == 0) { return(translator.PopValues(luaState, oldTop)); } else { ThrowExceptionFromError(oldTop); } } finally { executing = false; } } else { ThrowExceptionFromError(oldTop); } return(null); // Never reached - keeps compiler happy }
/* * Calls the object as a function with the provided arguments and * casting returned values to the types in returnTypes before returning * them in an array */ internal object[] CallFunction(object function, object[] args, Type[] returnTypes) { int nArgs = 0; int oldTop = LuaLib.LuaGetTop(luaState); if (!LuaLib.LuaCheckStack(luaState, args.Length + 6)) { throw new LuaException("Lua stack overflow"); } translator.Push(luaState, function); if (args != null) { nArgs = args.Length; for (int i = 0; i < args.Length; i++) { translator.Push(luaState, args [i]); } } executing = true; try { int error = LuaLib.LuaPCall(luaState, nArgs, -1, 0); if (error != 0) { ThrowExceptionFromError(oldTop); } } finally { executing = false; } return(returnTypes != null?translator.PopValues(luaState, oldTop, returnTypes) : translator.PopValues(luaState, oldTop)); }
/// <summary> /// Pops a value from the lua stack. /// </summary> /// <returns>Returns the top value from the lua stack.</returns> public object Pop() { int top = LuaLib.LuaGetTop(luaState); return(translator.PopValues(luaState, top - 1) [0]); }
/* * Matches a method against its arguments in the Lua stack. Returns * if the match was succesful. It it was also returns the information * necessary to invoke the method. */ internal bool MatchParameters(LuaState luaState, MethodBase method, ref MethodCache methodCache) { ExtractValue extractValue; bool isMethod = true; var paramInfo = method.GetParameters(); int currentLuaParam = 1; int nLuaParams = LuaLib.LuaGetTop(luaState); var paramList = new List <object> (); var outList = new List <int> (); var argTypes = new List <MethodArgs> (); foreach (var currentNetParam in paramInfo) { #if !SILVERLIGHT if (!currentNetParam.IsIn && currentNetParam.IsOut) // Skips out params #else if (currentNetParam.IsOut) // Skips out params #endif { paramList.Add(null); outList.Add(paramList.LastIndexOf(null)); } else if (IsTypeCorrect(luaState, currentLuaParam, currentNetParam, out extractValue)) // Type checking { var value = extractValue(luaState, currentLuaParam); paramList.Add(value); int index = paramList.LastIndexOf(value); var methodArg = new MethodArgs(); methodArg.index = index; methodArg.extractValue = extractValue; argTypes.Add(methodArg); if (currentNetParam.ParameterType.IsByRef) { outList.Add(index); } currentLuaParam++; } // Type does not match, ignore if the parameter is optional else if (IsParamsArray(luaState, currentLuaParam, currentNetParam, out extractValue)) { var paramArrayType = currentNetParam.ParameterType.GetElementType(); Func <int, object> extractDelegate = (currentParam) => { currentLuaParam++; return(extractValue(luaState, currentParam)); }; int count = (nLuaParams - currentLuaParam) + 1; Array paramArray = TableToArray(extractDelegate, paramArrayType, currentLuaParam, count); paramList.Add(paramArray); int index = paramList.LastIndexOf(paramArray); var methodArg = new MethodArgs(); methodArg.index = index; methodArg.extractValue = extractValue; methodArg.isParamsArray = true; methodArg.paramsArrayType = paramArrayType; argTypes.Add(methodArg); } else if (currentLuaParam > nLuaParams) // Adds optional parameters { if (currentNetParam.IsOptional) { paramList.Add(currentNetParam.DefaultValue); } else { isMethod = false; break; } } else if (currentNetParam.IsOptional) { paramList.Add(currentNetParam.DefaultValue); } else // No match { isMethod = false; break; } } if (currentLuaParam != nLuaParams + 1) // Number of parameters does not match { isMethod = false; } if (isMethod) { methodCache.args = paramList.ToArray(); methodCache.cachedMethod = method; methodCache.outList = outList.ToArray(); methodCache.argTypes = argTypes.ToArray(); } return(isMethod); }