public static int dofile(IntPtr L) { string fileName = String.Empty; fileName = LuaAPI.lua_tostring(L, 1); string lowerName = fileName.ToLower(); if (lowerName.EndsWith(".lua")) { int index = fileName.LastIndexOf('.'); fileName = fileName.Substring(0, index); } fileName = fileName.Replace('.', '/') + ".lua"; int n = LuaAPI.lua_gettop(L); byte[] text = Load(fileName); if (text == null) { return(LuaAPI.lua_gettop(L) - n); } if (LuaAPI.luaL_loadbuffer(L, text, text.Length, fileName) == 0) { LuaAPI.lua_pcall(L, 0, -1, 0); } return(LuaAPI.lua_gettop(L) - n); }
/* * Gets the values from the provided index to * the top of the stack and returns them in an array, casting * them to the provided types. */ internal object[] popValues(IntPtr luaState, int oldTop, Type[] popTypes) { int newTop = LuaAPI.lua_gettop(luaState); if (oldTop == newTop) { return(null); } else { int iTypes; List <object> returnValues = new List <object>(); if (popTypes[0] == typeof(void)) { iTypes = 1; } else { iTypes = 0; } for (int i = oldTop + 1; i <= newTop; i++) { returnValues.Add(getAsType(luaState, i, popTypes[iTypes])); iTypes++; } LuaAPI.lua_settop(luaState, oldTop); return(returnValues.ToArray()); } }
public static int print(IntPtr L) { int n = LuaAPI.lua_gettop(L); string s = String.Empty; LuaAPI.lua_getglobal(L, "tostring"); for (int i = 1; i <= n; i++) { LuaAPI.lua_pushvalue(L, -1); /* function to be called */ LuaAPI.lua_pushvalue(L, i); /* value to print */ if (0 != LuaAPI.lua_pcall(L, 1, 1, 0)) { return(LuaAPI.lua_error(L)); } s += LuaAPI.lua_tostring(L, -1); if (i != n) { s += "\t"; } LuaAPI.lua_pop(L, 1); } UnityEngine.Debug.Log("LUA: " + s); return(0); }
public object[] DoFile(string fileName) { int errFunc = LuaAPI.load_error_func(L, errorFuncRef); LuaAPI.lua_pushstdcallcfunction(L, LuaStatic.traceback); int oldTop = LuaAPI.lua_gettop(L); byte[] bytes = LuaStatic.Load(fileName); if (bytes == null) { LuaAPI.lua_pop(L, 1); return(null); } if (LuaAPI.luaL_loadbuffer(L, bytes, bytes.Length, fileName) == 0) { if (LuaAPI.lua_pcall(L, 0, LuaAPI.LUA_MULTRET, errFunc) == 0) { object[] results = translator.popValues(L, oldTop); LuaAPI.lua_remove(L, errFunc); LuaAPI.lua_pop(L, 1); return(results); } else { ThrowExceptionFromError(oldTop); LuaAPI.lua_pop(L, 1); } } else { ThrowExceptionFromError(oldTop); LuaAPI.lua_pop(L, 1); } return(null); }
public int BeginPCall() { LuaScriptMgr.PushTraceBack(L); beginPos = LuaAPI.lua_gettop(L); push(L); return(beginPos); }
public static int loader(IntPtr L) { string fileName = string.Empty; fileName = LuaAPI.lua_tostring(L, 1); string lowerName = fileName.ToLower(); if (lowerName.EndsWith(".lua")) { int index = fileName.LastIndexOf('.'); fileName = fileName.Substring(0, index); } fileName = fileName.Replace('.', '/'); int oldTop = LuaAPI.lua_gettop(L); LuaAPI.lua_pushstdcallcfunction(L, LuaStatic.traceback); byte[] text = LuaStatic.Load(fileName); if (text == null) { LuaAPI.lua_pop(L, 1); return(0); } if (LuaAPI.luaL_loadbuffer(L, text, text.Length, fileName) != 0) { LuaScriptMgr mgr = LuaScriptMgr.GetMgrFromLuaState(L); if (mgr != null) { mgr.lua.ThrowExceptionFromError(oldTop + 1); } LuaAPI.lua_pop(L, 1); } return(1); }
internal void setObject(int reference, string field, object val) { int oldTop = LuaAPI.lua_gettop(L); LuaAPI.ulua_rawgeti(L, LuaAPI.LUA_REGISTRYINDEX, reference); setObject(field.Split(new char[] { '.' }), val); LuaAPI.lua_settop(L, oldTop); }
internal object getObject(int reference, string field) { int oldTop = LuaAPI.lua_gettop(L); LuaAPI.ulua_rawgeti(L, LuaAPI.LUA_REGISTRYINDEX, reference); object returnValue = getObject(field.Split(new char[] { '.' })); LuaAPI.lua_settop(L, oldTop); return(returnValue); }
internal object getObject(int reference, object field) { int oldTop = LuaAPI.lua_gettop(L); LuaAPI.ulua_rawgeti(L, LuaAPI.LUA_REGISTRYINDEX, reference); translator.push(L, field); LuaAPI.lua_gettable(L, -2); object returnValue = translator.getObject(L, -1); LuaAPI.lua_settop(L, oldTop); return(returnValue); }
internal object rawGetObject(int reference, string field) { int oldTop = LuaAPI.lua_gettop(L); LuaAPI.ulua_rawgeti(L, LuaAPI.LUA_REGISTRYINDEX, reference); LuaAPI.lua_pushstring(L, field); LuaAPI.lua_rawget(L, -2); object obj = translator.getObject(L, -1); LuaAPI.lua_settop(L, oldTop); return(obj); }
public LuaFunction LoadString(string chunk, string name) { int oldTop = LuaAPI.lua_gettop(L); byte[] bt = Encoding.UTF8.GetBytes(chunk); if (LuaAPI.luaL_loadbuffer(L, bt, bt.Length, name) != 0) { ThrowExceptionFromError(oldTop); } LuaFunction result = translator.getFunction(L, -1); translator.popValues(L, oldTop); return(result); }
public ListDictionary GetTableDict(LuaTable table) { ListDictionary dict = new ListDictionary(); int oldTop = LuaAPI.lua_gettop(L); translator.push(L, table); LuaAPI.lua_pushnil(L); while (LuaAPI.lua_next(L, -2) != 0) { dict[translator.getObject(L, -2)] = translator.getObject(L, -1); LuaAPI.lua_settop(L, -2); } LuaAPI.lua_settop(L, oldTop); return(dict); }
public object this[string fullPath] { get { object returnValue = null; int oldTop = LuaAPI.lua_gettop(L); string[] path = fullPath.Split(new char[] { '.' }); LuaAPI.lua_getglobal(L, path[0]); returnValue = translator.getObject(L, -1); if (path.Length > 1) { string[] remainingPath = new string[path.Length - 1]; Array.Copy(path, 1, remainingPath, 0, path.Length - 1); returnValue = getObject(remainingPath); } LuaAPI.lua_settop(L, oldTop); return(returnValue); } set { int oldTop = LuaAPI.lua_gettop(L); string[] path = fullPath.Split(new char[] { '.' }); if (path.Length == 1) { translator.push(L, value); LuaAPI.lua_setglobal(L, fullPath); } else { LuaAPI.lua_getglobal(L, path[0]); LuaTypes type = LuaAPI.lua_type(L, -1); if (type == LuaTypes.LUA_TNIL) { Debugger.LogError("Table {0} not exists", path[0]); LuaAPI.lua_settop(L, oldTop); return; } string[] remainingPath = new string[path.Length - 1]; Array.Copy(path, 1, remainingPath, 0, path.Length - 1); setObject(remainingPath, value); } LuaAPI.lua_settop(L, oldTop); } }
/* * Calls the function casting return values to the types * in returnTypes */ internal object[] call(object[] args, Type[] returnTypes) { int nArgs = 0; LuaScriptMgr.PushTraceBack(L); int oldTop = LuaAPI.lua_gettop(L); if (!LuaAPI.lua_checkstack(L, args.Length + 6)) { LuaAPI.lua_pop(L, 1); throw new LuaException("Lua stack overflow"); } push(L); if (args != null) { nArgs = args.Length; for (int i = 0; i < args.Length; i++) { PushArgs(L, args[i]); } } int error = LuaAPI.lua_pcall(L, nArgs, -1, -nArgs - 2); if (error != 0) { string err = LuaAPI.lua_tostring(L, -1); LuaAPI.lua_settop(L, oldTop - 1); if (err == null) { err = "Unknown Lua Error"; } throw new LuaScriptException(err, ""); } object[] ret = returnTypes != null?translator.popValues(L, oldTop, returnTypes) : translator.popValues(L, oldTop); LuaAPI.lua_settop(L, oldTop - 1); return(ret); }
/// <summary> /// Debug tool to dump the lua stack /// </summary> public static void dumpStack(ObjectTranslator translator, IntPtr luaState) { int depth = LuaAPI.lua_gettop(luaState); Debug.WriteLine("lua stack depth: " + depth); for (int i = 1; i <= depth; i++) { LuaTypes type = LuaAPI.lua_type(luaState, i); // we dump stacks when deep in calls, calling typename while the stack is in flux can fail sometimes, so manually check for key types string typestr = (type == LuaTypes.LUA_TTABLE) ? "table" : LuaAPI.lua_typename(luaState, type); string strrep = LuaAPI.lua_tostring(luaState, i); if (type == LuaTypes.LUA_TUSERDATA) { object obj = translator.getRawNetObject(luaState, i); strrep = obj.ToString(); } Debug.WriteLine(String.Format("{0}: ({1}) {2}", i, typestr, strrep)); } }
internal object[] popValues(IntPtr luaState, int oldTop) { int newTop = LuaAPI.lua_gettop(luaState); if (oldTop == newTop) { return(null); } else { List <object> returnValues = new List <object>(); for (int i = oldTop + 1; i <= newTop; i++) { returnValues.Add(getObject(luaState, i)); } LuaAPI.lua_settop(luaState, oldTop); return(returnValues.ToArray()); } }
public object[] DoString(string chunk) { int oldTop = LuaAPI.lua_gettop(L); int errFunc = LuaAPI.load_error_func(L, errorFuncRef); byte[] bt = Encoding.UTF8.GetBytes(chunk); if (LuaAPI.luaL_loadbuffer(L, bt, bt.Length, "chunk") == 0) { if (LuaAPI.lua_pcall(L, 0, LuaAPI.LUA_MULTRET, errFunc) == 0) { LuaAPI.lua_remove(L, errFunc); return(translator.popValues(L, oldTop)); } else { ThrowExceptionFromError(oldTop); } } else { ThrowExceptionFromError(oldTop); } return(null); }
internal ExtractValue checkType(IntPtr luaState, int stackPos, Type paramType) { LuaTypes luatype = LuaAPI.lua_type(luaState, stackPos); if (paramType.IsByRef) { paramType = paramType.GetElementType(); } Type underlyingType = Nullable.GetUnderlyingType(paramType); if (underlyingType != null) { paramType = underlyingType; // Silently convert nullable types to their non null requics } long runtimeHandleValue = paramType.TypeHandle.Value.ToInt64(); if (paramType.Equals(typeof(object))) { return(extractValues[runtimeHandleValue]); } //CP: Added support for generic parameters if (paramType.IsGenericParameter) { if (luatype == LuaTypes.LUA_TBOOLEAN) { return(extractValues[typeof(bool).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TSTRING) { return(extractValues[typeof(string).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TTABLE) { return(extractValues[typeof(LuaTable).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TUSERDATA) { return(extractValues[typeof(object).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TFUNCTION) { return(extractValues[typeof(LuaFunction).TypeHandle.Value.ToInt64()]); } else if (luatype == LuaTypes.LUA_TNUMBER) { return(extractValues[typeof(double).TypeHandle.Value.ToInt64()]); } } if (paramType.IsValueType && luatype == LuaTypes.LUA_TTABLE) { int oldTop = LuaAPI.lua_gettop(luaState); ExtractValue ret = null; LuaAPI.lua_pushvalue(luaState, stackPos); LuaAPI.lua_pushstring(luaState, "class"); LuaAPI.lua_gettable(luaState, -2); if (!LuaAPI.lua_isnil(luaState, -1)) { string cls = LuaAPI.lua_tostring(luaState, -1); if (cls == "Vector3" && paramType == typeof(Vector3)) { ret = extractValues[typeof(Vector3).TypeHandle.Value.ToInt64()]; } else if (cls == "Vector2" && paramType == typeof(Vector2)) { ret = extractValues[typeof(Vector2).TypeHandle.Value.ToInt64()]; } else if (cls == "Quaternion" && paramType == typeof(Quaternion)) { ret = extractValues[typeof(Quaternion).TypeHandle.Value.ToInt64()]; } else if (cls == "Color" && paramType == typeof(Color)) { ret = extractValues[typeof(Color).TypeHandle.Value.ToInt64()]; } else if (cls == "Vector4" && paramType == typeof(Vector4)) { ret = extractValues[typeof(Vector4).TypeHandle.Value.ToInt64()]; } else if (cls == "Ray" && paramType == typeof(Ray)) { ret = extractValues[typeof(Ray).TypeHandle.Value.ToInt64()]; } else { ret = null; } } LuaAPI.lua_settop(luaState, oldTop); if (ret != null) { return(ret); } } if (LuaAPI.lua_isnumber(luaState, stackPos)) { return(extractValues[runtimeHandleValue]); } if (paramType == typeof(bool)) { if (LuaAPI.lua_isboolean(luaState, stackPos)) { return(extractValues[runtimeHandleValue]); } } else if (paramType == typeof(string)) { if (LuaAPI.lua_isstring(luaState, stackPos)) { return(extractValues[runtimeHandleValue]); } else if (luatype == LuaTypes.LUA_TNIL) { return(extractNetObject); // kevinh - silently convert nil to a null string pointer } } else if (paramType == typeof(LuaTable)) { if (luatype == LuaTypes.LUA_TTABLE) { return(extractValues[runtimeHandleValue]); } } else if (paramType == typeof(LuaFunction)) { if (luatype == LuaTypes.LUA_TFUNCTION) { return(extractValues[runtimeHandleValue]); } } else if (typeof(Delegate).IsAssignableFrom(paramType) && luatype == LuaTypes.LUA_TFUNCTION) { translator.throwError(luaState, "Delegates not implemnented"); } else if (paramType.IsInterface && luatype == LuaTypes.LUA_TTABLE) { translator.throwError(luaState, "Interfaces not implemnented"); } else if ((paramType.IsInterface || paramType.IsClass) && luatype == LuaTypes.LUA_TNIL) { // kevinh - allow nil to be silently converted to null - extractNetObject will return null when the item ain't found return(extractNetObject); } else if (LuaAPI.lua_type(luaState, stackPos) == LuaTypes.LUA_TTABLE) { if (LuaTypes.LUA_TNIL != LuaAPI.luaL_getmetafield(luaState, stackPos, "__index")) { object obj = translator.getNetObject(luaState, -1); LuaAPI.lua_settop(luaState, -2); if (obj != null && paramType.IsAssignableFrom(obj.GetType())) { return(extractNetObject); } } } else { //object obj = translator.getNetObject(luaState, stackPos); //topameng 修改这里使支持注册到c#的lua类 object obj = translator.getRawNetObject(luaState, stackPos); if (obj != null && paramType.IsAssignableFrom(obj.GetType())) { return(extractNetObject); } } return(null); }
/* * 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(IntPtr luaState, MethodBase method, ref MethodCache methodCache) { ExtractValue extractValue; bool isMethod = true; ParameterInfo[] paramInfo = method.GetParameters(); int currentLuaParam = 1; int nLuaParams = LuaAPI.lua_gettop(luaState); ArrayList paramList = new ArrayList(); List <int> outList = new List <int>(); List <MethodArgs> argTypes = new List <MethodArgs>(); foreach (ParameterInfo currentNetParam in paramInfo) { if (!currentNetParam.IsIn && currentNetParam.IsOut) // Skips out params { outList.Add(paramList.Add(null)); } else if (currentLuaParam > nLuaParams) // Adds optional parameters { if (currentNetParam.IsOptional) { paramList.Add(currentNetParam.DefaultValue); } else { isMethod = false; break; } } else if (_IsTypeCorrect(luaState, currentLuaParam, currentNetParam, out extractValue)) // Type checking { int index = paramList.Add(extractValue(luaState, currentLuaParam)); MethodArgs 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)) { object luaParamValue = extractValue(luaState, currentLuaParam); Type paramArrayType = currentNetParam.ParameterType.GetElementType(); Array paramArray = TableToArray(luaParamValue, paramArrayType); int index = paramList.Add(paramArray); MethodArgs methodArg = new MethodArgs(); methodArg.index = index; methodArg.extractValue = extractValue; methodArg.isParamsArray = true; methodArg.paramsArrayType = paramArrayType; argTypes.Add(methodArg); currentLuaParam++; } 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); }
public int call(IntPtr luaState) { object targetObject; bool failedCall = true; int nReturnValues = 0; if (!LuaAPI.lua_checkstack(luaState, 5)) { throw new LuaException("Lua stack overflow"); } bool isStatic = (_BindingType & BindingFlags.Static) == BindingFlags.Static; SetPendingException(null); if (isStatic) { targetObject = null; } else { targetObject = _ExtractTarget(luaState, 1); } if (_LastCalledMethod.cachedMethod != null) // Cached? { int numStackToSkip = isStatic ? 0 : 1; // If this is an instance invoe we will have an extra arg on the stack for the targetObject int numArgsPassed = LuaAPI.lua_gettop(luaState) - numStackToSkip; MethodBase method = _LastCalledMethod.cachedMethod; if (numArgsPassed == _LastCalledMethod.argTypes.Length) // No. of args match? { if (!LuaAPI.lua_checkstack(luaState, _LastCalledMethod.outList.Length + 6)) { throw new LuaException("Lua stack overflow"); } //这里 args 只是将 _LastCalledMethod.args 拿来做缓冲区用,避免内存再分配, 里面的值是可以干掉的 object[] args = _LastCalledMethod.args; try { for (int i = 0; i < _LastCalledMethod.argTypes.Length; i++) { MethodArgs type = _LastCalledMethod.argTypes[i]; object luaParamValue = type.extractValue(luaState, i + 1 + numStackToSkip); if (_LastCalledMethod.argTypes[i].isParamsArray) { args[type.index] = _Translator.tableToArray(luaParamValue, type.paramsArrayType); } else { args[type.index] = luaParamValue; } if (args[type.index] == null && !LuaAPI.lua_isnil(luaState, i + 1 + numStackToSkip)) { throw new LuaException("argument number " + (i + 1) + " is invalid"); } } if ((_BindingType & BindingFlags.Static) == BindingFlags.Static) { _Translator.push(luaState, method.Invoke(null, args)); } else { if (_LastCalledMethod.cachedMethod.IsConstructor) { _Translator.push(luaState, ((ConstructorInfo)method).Invoke(args)); } else { _Translator.push(luaState, method.Invoke(targetObject, args)); } } failedCall = false; } catch (TargetInvocationException e) { return(SetPendingException(e.GetBaseException())); } catch (Exception e) { if (_Members.Length == 1) { return(SetPendingException(e)); } } } } // Cache miss if (failedCall) { if (!isStatic) { if (targetObject == null) { _Translator.throwError(luaState, String.Format("instance method '{0}' requires a non null target object", _MethodName)); LuaAPI.lua_pushnil(luaState); return(1); } LuaAPI.lua_remove(luaState, 1); // Pops the receiver } bool hasMatch = false; string candidateName = null; foreach (MemberInfo member in _Members) { candidateName = member.ReflectedType.Name + "." + member.Name; MethodBase m = (MethodInfo)member; bool isMethod = _Translator.matchParameters(luaState, m, ref _LastCalledMethod); if (isMethod) { hasMatch = true; break; } } if (!hasMatch) { string msg = (candidateName == null) ? "invalid arguments to method call" : ("invalid arguments to method: " + candidateName); LuaAPI.luaL_error(luaState, msg); LuaAPI.lua_pushnil(luaState); ClearCachedArgs(); return(1); } } if (failedCall) { if (!LuaAPI.lua_checkstack(luaState, _LastCalledMethod.outList.Length + 6)) { ClearCachedArgs(); throw new LuaException("Lua stack overflow"); } try { if (isStatic) { _Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(null, _LastCalledMethod.args)); } else { if (_LastCalledMethod.cachedMethod.IsConstructor) { _Translator.push(luaState, ((ConstructorInfo)_LastCalledMethod.cachedMethod).Invoke(_LastCalledMethod.args)); } else { _Translator.push(luaState, _LastCalledMethod.cachedMethod.Invoke(targetObject, _LastCalledMethod.args)); } } } catch (TargetInvocationException e) { ClearCachedArgs(); return(SetPendingException(e.GetBaseException())); } catch (Exception e) { ClearCachedArgs(); return(SetPendingException(e)); } } // Pushes out and ref return values for (int index = 0; index < _LastCalledMethod.outList.Length; index++) { nReturnValues++; _Translator.push(luaState, _LastCalledMethod.args[_LastCalledMethod.outList[index]]); } //Desc: // if not return void,we need add 1, // or we will lost the function's return value // when call dotnet function like "int foo(arg1,out arg2,out arg3)" in lua code if (!_LastCalledMethod.IsReturnVoid && nReturnValues > 0) { nReturnValues++; } ClearCachedArgs(); return(nReturnValues < 1 ? 1 : nReturnValues); }