/* * 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 = LuaDLL.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 static int callConstructor(IntPtr luaState) { ObjectTranslator translator = ObjectTranslator.FromState(luaState); MethodCache validConstructor = new MethodCache(); IReflect klass; object obj = translator.getRawNetObject(luaState, 1); if (obj == null || !(obj is IReflect)) { LuaDLL.luaL_error(luaState, "trying to call constructor on an invalid type reference"); LuaDLL.lua_pushnil(luaState); return 1; } else klass = (IReflect)obj; LuaDLL.lua_remove(luaState, 1); ConstructorInfo[] constructors = klass.UnderlyingSystemType.GetConstructors(); foreach (ConstructorInfo constructor in constructors) { bool isConstructor = translator.metaFunctions.matchParameters(luaState, constructor, ref validConstructor); if (isConstructor) { try { translator.push(luaState, constructor.Invoke(validConstructor.args)); } catch (TargetInvocationException e) { translator.metaFunctions.ThrowError(luaState, e); LuaDLL.lua_pushnil(luaState); } catch { LuaDLL.lua_pushnil(luaState); } return 1; } } string constructorName = (constructors.Length == 0) ? "unknown" : constructors[0].Name; LuaDLL.luaL_error(luaState, String.Format("{0} does not contain constructor({1}) argument match", klass.UnderlyingSystemType, constructorName)); LuaDLL.lua_pushnil(luaState); return 1; }