public static int getConstructorSignature(IntPtr luaState) { ObjectTranslator objectTranslator = ObjectTranslator.FromState(luaState); IReflect reflect = null; int num = LuaDLL.luanet_checkudata(luaState, 1, "luaNet_class"); if (num != -1) { reflect = (IReflect)objectTranslator.objects[num]; } if (reflect == null) { objectTranslator.throwError(luaState, "get_constructor_bysig: first arg is invalid type reference"); } Type[] array = new Type[LuaDLL.lua_gettop(luaState) - 1]; for (int i = 0; i < array.Length; i++) { array[i] = objectTranslator.FindType(LuaDLL.lua_tostring(luaState, i + 2)); } try { ConstructorInfo constructor = reflect.UnderlyingSystemType.GetConstructor(array); objectTranslator.pushFunction(luaState, new LuaCSFunction(new LuaMethodWrapper(objectTranslator, null, reflect, constructor).call)); } catch (Exception ex) { objectTranslator.throwError(luaState, ex.Message); LuaDLL.lua_pushnil(luaState); } return(1); }
public static int unregisterTable(IntPtr luaState) { ObjectTranslator translator = ObjectTranslator.FromState(luaState); try { if (LuaDLL.lua_getmetatable(luaState, 1) != 0) { LuaDLL.lua_pushstring(luaState, "__index"); LuaDLL.lua_gettable(luaState, -2); object obj = translator.getRawNetObject(luaState, -1); if (obj == null) translator.throwError(luaState, "unregister_table: arg is not valid table"); FieldInfo luaTableField = obj.GetType().GetField("__luaInterface_luaTable"); if (luaTableField == null) translator.throwError(luaState, "unregister_table: arg is not valid table"); luaTableField.SetValue(obj, null); LuaDLL.lua_pushnil(luaState); LuaDLL.lua_setmetatable(luaState, 1); LuaDLL.lua_pushstring(luaState, "base"); LuaDLL.lua_pushnil(luaState); LuaDLL.lua_settable(luaState, 1); } else translator.throwError(luaState, "unregister_table: arg is not valid table"); } catch (Exception e) { translator.throwError(luaState, e.Message); } return 0; }
public static int getConstructorSignature(IntPtr luaState) { ObjectTranslator translator = ObjectTranslator.FromState(luaState); IReflect klass = null; int udata = LuaDLL.luanet_checkudata(luaState, 1, "luaNet_class"); if (udata != -1) { klass = (IReflect)translator.objects[udata]; } if (klass == null) { translator.throwError(luaState, "get_constructor_bysig: first arg is invalid type reference"); } Type[] signature = new Type[LuaDLL.lua_gettop(luaState) - 1]; for (int i = 0; i < signature.Length; i++) signature[i] = translator.FindType(LuaDLL.lua_tostring(luaState, i + 2)); try { ConstructorInfo constructor = klass.UnderlyingSystemType.GetConstructor(signature); translator.pushFunction(luaState, new LuaCSFunction((new LuaMethodWrapper(translator, null, klass, constructor)).call)); } catch (Exception e) { translator.throwError(luaState, e.Message); LuaDLL.lua_pushnil(luaState); } return 1; }
public static int setFieldOrProperty(IntPtr luaState) { ObjectTranslator objectTranslator = ObjectTranslator.FromState(luaState); object rawNetObject = objectTranslator.getRawNetObject(luaState, 1); if (rawNetObject == null) { objectTranslator.throwError(luaState, "trying to index and invalid object reference"); return(0); } Type type = rawNetObject.GetType(); string message; bool flag = objectTranslator.metaFunctions.trySetMember(luaState, type, rawNetObject, BindingFlags.IgnoreCase | BindingFlags.Instance, out message); if (flag) { return(0); } try { if (type.IsArray && LuaDLL.lua_isnumber(luaState, 2)) { int index = (int)LuaDLL.lua_tonumber(luaState, 2); Array array = (Array)rawNetObject; object asType = objectTranslator.getAsType(luaState, 3, array.GetType().GetElementType()); array.SetValue(asType, index); } else { MethodInfo method = type.GetMethod("set_Item"); if (method != null) { ParameterInfo[] parameters = method.GetParameters(); Type parameterType = parameters[1].ParameterType; object asType2 = objectTranslator.getAsType(luaState, 3, parameterType); Type parameterType2 = parameters[0].ParameterType; object asType3 = objectTranslator.getAsType(luaState, 2, parameterType2); method.Invoke(rawNetObject, new object[] { asType3, asType2 }); } else { objectTranslator.throwError(luaState, message); } } } catch (SEHException) { throw; } catch (Exception e) { objectTranslator.metaFunctions.ThrowError(luaState, e); } return(0); }
/// <summary>__tostring metafunction of CLR objects.</summary> int toString(lua.State L) { Debug.Assert(translator.interpreter.IsSameLua(L) && luanet.infunction(L)); var obj = luaclr.checkref(L, 1); string s; try { s = obj.ToString(); } catch (Exception ex) { return(translator.throwError(L, ex)); } lua.pushstring(L, s ?? ""); return(1); }
public static int registerTable(IntPtr luaState) { #if __NOGEN__ throwError(luaState, "Tables as Objects not implemnented"); #else ObjectTranslator translator = ObjectTranslator.FromState(luaState); if (LuaDLL.lua_type(luaState, 1) == LuaTypes.LUA_TTABLE) { LuaTable luaTable = translator.getTable(luaState, 1); string superclassName = LuaDLL.lua_tostring(luaState, 2); if (superclassName != null) { Type klass = translator.FindType(superclassName); if (klass != null) { // Creates and pushes the object in the stack, setting // it as the metatable of the first argument object obj = CodeGeneration.Instance.GetClassInstance(klass, luaTable); translator.pushObject(luaState, obj, "luaNet_metatable"); LuaDLL.lua_newtable(luaState); LuaDLL.lua_pushstring(luaState, "__index"); LuaDLL.lua_pushvalue(luaState, -3); LuaDLL.lua_settable(luaState, -3); LuaDLL.lua_pushstring(luaState, "__newindex"); LuaDLL.lua_pushvalue(luaState, -3); LuaDLL.lua_settable(luaState, -3); LuaDLL.lua_setmetatable(luaState, 1); // Pushes the object again, this time as the base field // of the table and with the luaNet_searchbase metatable LuaDLL.lua_pushstring(luaState, "base"); int index = translator.addObject(obj); translator.pushNewObject(luaState, obj, index, "luaNet_searchbase"); LuaDLL.lua_rawset(luaState, 1); } else { translator.throwError(luaState, "register_table: can not find superclass '" + superclassName + "'"); } } else { translator.throwError(luaState, "register_table: superclass name can not be null"); } } else { translator.throwError(luaState, "register_table: first arg is not a table"); } #endif return(0); }
/// <summary> /// Convert C# exceptions into Lua errors /// </summary> /// <returns>num of things on stack</returns> /// <param name="e">null for no pending exception</param> internal int SetPendingException(Exception e) { if (e != null) { translator.throwError(L, e.ToString()); LuaDLL.lua_pushnil(L); return(1); } else { return(0); } }
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)) { translator.throwError(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; translator.throwError(luaState, String.Format("{0} does not contain constructor({1}) argument match", klass.UnderlyingSystemType, constructorName)); LuaDLL.lua_pushnil(luaState); return(1); }
public static int loadAssembly(IntPtr luaState) { ObjectTranslator objectTranslator = ObjectTranslator.FromState(luaState); try { string text = LuaDLL.lua_tostring(luaState, 1); Assembly assembly = null; try { assembly = Assembly.Load(text); } catch (BadImageFormatException) { } if (assembly == null) { assembly = Assembly.Load(AssemblyName.GetAssemblyName(text)); } if (assembly != null && !objectTranslator.assemblies.Contains(assembly)) { objectTranslator.assemblies.Add(assembly); } } catch (Exception ex) { objectTranslator.throwError(luaState, ex.Message); } return(0); }
public static int getBaseMethod(IntPtr luaState) { ObjectTranslator translator = ObjectTranslator.FromState(luaState); object obj = translator.getRawNetObject(luaState, 1); if (obj == null) { translator.throwError(luaState, "trying to index an invalid object reference"); LuaDLL.lua_pushnil(luaState); LuaDLL.lua_pushboolean(luaState, false); return(2); } string methodName = LuaDLL.lua_tostring(luaState, 2); if (methodName == null) { LuaDLL.lua_pushnil(luaState); LuaDLL.lua_pushboolean(luaState, false); return(2); } translator.metaFunctions.getMember(luaState, obj.GetType(), obj, "__luaInterface_base_" + methodName, BindingFlags.Instance | BindingFlags.IgnoreCase); LuaDLL.lua_settop(luaState, -2); if (LuaDLL.lua_type(luaState, -1) == LuaTypes.LUA_TNIL) { LuaDLL.lua_settop(luaState, -2); return(translator.metaFunctions.getMember(luaState, obj.GetType(), obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase)); } LuaDLL.lua_pushboolean(luaState, false); return(2); }
/// <summary> /// Convert C# exceptions into Lua errors /// </summary> /// <returns>num of things on stack</returns> /// <param name="e">null for no pending exception</param> internal int SetPendingException(Exception e) { Exception caughtExcept = e; if (caughtExcept != null) { translator.throwError(L, caughtExcept); LuaDLL.lua_pushnil(L); return(1); } else { return(0); } }
public static int getClassMethod(IntPtr luaState) { ObjectTranslator objectTranslator = ObjectTranslator.FromState(luaState); object rawNetObject = objectTranslator.getRawNetObject(luaState, 1); if (rawNetObject == null || !(rawNetObject is IReflect)) { objectTranslator.throwError(luaState, "trying to index an invalid type reference"); LuaDLL.lua_pushnil(luaState); return(1); } IReflect reflect = (IReflect)rawNetObject; if (LuaDLL.lua_isnumber(luaState, 2)) { int length = (int)LuaDLL.lua_tonumber(luaState, 2); objectTranslator.push(luaState, Array.CreateInstance(reflect.UnderlyingSystemType, length)); return(1); } string text = LuaDLL.lua_tostring(luaState, 2); if (text == null) { LuaDLL.lua_pushnil(luaState); return(1); } return(objectTranslator.metaFunctions.getMember(luaState, reflect, null, text, BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.FlattenHierarchy)); }
public static int loadAssembly(IntPtr luaState) { ObjectTranslator translator = ObjectTranslator.FromState(luaState); try { string assemblyName = LuaAPI.lua_tostring(luaState, 1); Assembly assembly = null; try { assembly = Assembly.Load(assemblyName); } catch (BadImageFormatException) { // The assemblyName was invalid. It is most likely a path. } if (assembly == null) { assembly = Assembly.Load(AssemblyName.GetAssemblyName(assemblyName)); } if (assembly != null && !translator.assemblies.Contains(assembly)) { translator.assemblies.Add(assembly); } } catch (Exception e) { translator.throwError(luaState, e.Message); } return(0); }
public static int registerTable(IntPtr luaState) { ObjectTranslator objectTranslator = ObjectTranslator.FromState(luaState); if (LuaDLL.lua_type(luaState, 1) == LuaTypes.LUA_TTABLE) { LuaTable table = objectTranslator.getTable(luaState, 1); string text = LuaDLL.lua_tostring(luaState, 2); if (text != null) { Type type = objectTranslator.FindType(text); if (type != null) { object classInstance = CodeGeneration.Instance.GetClassInstance(type, table); objectTranslator.pushObject(luaState, classInstance, "luaNet_metatable"); LuaDLL.lua_newtable(luaState); LuaDLL.lua_pushstring(luaState, "__index"); LuaDLL.lua_pushvalue(luaState, -3); LuaDLL.lua_settable(luaState, -3); LuaDLL.lua_pushstring(luaState, "__newindex"); LuaDLL.lua_pushvalue(luaState, -3); LuaDLL.lua_settable(luaState, -3); LuaDLL.lua_setmetatable(luaState, 1); LuaDLL.lua_pushstring(luaState, "base"); int index = objectTranslator.addObject(classInstance); objectTranslator.pushNewObject(luaState, classInstance, index, "luaNet_searchbase"); LuaDLL.lua_rawset(luaState, 1); } else { objectTranslator.throwError(luaState, "register_table: can not find superclass '" + text + "'"); } } else { objectTranslator.throwError(luaState, "register_table: superclass name can not be null"); } } else { objectTranslator.throwError(luaState, "register_table: first arg is not a table"); } return(0); }
public static int getMethodSignature(IntPtr luaState) { ObjectTranslator translator = ObjectTranslator.FromState(luaState); IReflect klass; object target; int udata = LuaDLL.luanet_checkudata(luaState, 1, "luaNet_class"); if (udata != -1) { klass = (IReflect)translator.objects[udata]; target = null; } else { target = translator.getRawNetObject(luaState, 1); if (target == null) { translator.throwError(luaState, "get_method_bysig: first arg is not type or object reference"); LuaDLL.lua_pushnil(luaState); return(1); } klass = target.GetType(); } string methodName = LuaDLL.lua_tostring(luaState, 2); Type[] signature = new Type[LuaDLL.lua_gettop(luaState) - 2]; for (int i = 0; i < signature.Length; i++) { signature[i] = translator.FindType(LuaDLL.lua_tostring(luaState, i + 3)); } try { //CP: Added ignore case MethodInfo method = klass.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.IgnoreCase, null, signature, null); translator.pushFunction(luaState, new LuaCSFunction((new LuaMethodWrapper(translator, target, klass, method)).call)); } catch (Exception e) { translator.throwError(luaState, e.Message); LuaDLL.lua_pushnil(luaState); } return(1); }
public static int getMethodSignature(IntPtr luaState) { ObjectTranslator objectTranslator = ObjectTranslator.FromState(luaState); int num = LuaDLL.luanet_checkudata(luaState, 1, "luaNet_class"); IReflect reflect; object obj; if (num != -1) { reflect = (IReflect)objectTranslator.objects[num]; obj = null; } else { obj = objectTranslator.getRawNetObject(luaState, 1); if (obj == null) { objectTranslator.throwError(luaState, "get_method_bysig: first arg is not type or object reference"); LuaDLL.lua_pushnil(luaState); return(1); } reflect = obj.GetType(); } string name = LuaDLL.lua_tostring(luaState, 2); Type[] array = new Type[LuaDLL.lua_gettop(luaState) - 2]; for (int i = 0; i < array.Length; i++) { array[i] = objectTranslator.FindType(LuaDLL.lua_tostring(luaState, i + 3)); } try { MethodInfo method = reflect.GetMethod(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy, null, array, null); objectTranslator.pushFunction(luaState, new LuaCSFunction(new LuaMethodWrapper(objectTranslator, obj, reflect, method).call)); } catch (Exception ex) { objectTranslator.throwError(luaState, ex.Message); LuaDLL.lua_pushnil(luaState); } return(1); }
/// <summary>__tostring metafunction of CLR objects.</summary> int toString(lua.State L) { Debug.Assert(interpreter.IsSameLua(L) && luanet.infunction(L)); var obj = luaclr.checkref(L, 1); string s; var c = luanet.entercfunction(L, interpreter); try { s = obj.ToString(); } catch (LuaInternalException) { throw; } catch (Exception ex) { return(translator.throwError(L, ex)); } finally { c.Dispose(); } lua.pushstring(L, s ?? ""); return(1); }
public static int unregisterTable(IntPtr luaState) { ObjectTranslator objectTranslator = ObjectTranslator.FromState(luaState); try { if (LuaDLL.lua_getmetatable(luaState, 1) != 0) { LuaDLL.lua_pushstring(luaState, "__index"); LuaDLL.lua_gettable(luaState, -2); object rawNetObject = objectTranslator.getRawNetObject(luaState, -1); if (rawNetObject == null) { objectTranslator.throwError(luaState, "unregister_table: arg is not valid table"); } FieldInfo field = rawNetObject.GetType().GetField("__luaInterface_luaTable"); if (field == null) { objectTranslator.throwError(luaState, "unregister_table: arg is not valid table"); } field.SetValue(rawNetObject, null); LuaDLL.lua_pushnil(luaState); LuaDLL.lua_setmetatable(luaState, 1); LuaDLL.lua_pushstring(luaState, "base"); LuaDLL.lua_pushnil(luaState); LuaDLL.lua_settable(luaState, 1); } else { objectTranslator.throwError(luaState, "unregister_table: arg is not valid table"); } } catch (Exception ex) { objectTranslator.throwError(luaState, ex.Message); } return(0); }
public static int setClassFieldOrProperty(IntPtr luaState) { ObjectTranslator objectTranslator = ObjectTranslator.FromState(luaState); object rawNetObject = objectTranslator.getRawNetObject(luaState, 1); if (rawNetObject == null || !(rawNetObject is IReflect)) { objectTranslator.throwError(luaState, "trying to index an invalid type reference"); return(0); } IReflect targetType = (IReflect)rawNetObject; return(objectTranslator.metaFunctions.setMember(luaState, targetType, null, BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.FlattenHierarchy)); }
/// <summary> /// Convert C# exceptions into Lua errors /// </summary> /// <returns>num of things on stack</returns> /// <param name = "e">null for no pending exception</param> internal int SetPendingException(Exception e) { var caughtExcept = e; if (!caughtExcept.IsNull()) { translator.throwError(luaState, caughtExcept); LuaLib.lua_pushnil(luaState); return(1); } else { return(0); } }
public static int setClassFieldOrProperty(IntPtr luaState) { ObjectTranslator translator = ObjectTranslator.FromState(luaState); IReflect target; object obj = translator.getRawNetObject(luaState, 1); if (obj == null || !(obj is IReflect)) { translator.throwError(luaState, "trying to index an invalid type reference"); return(0); } else { target = (IReflect)obj; } return(translator.metaFunctions.setMember(luaState, target, null, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.IgnoreCase)); }
public static int getClassMethod(IntPtr luaState) { ObjectTranslator translator = ObjectTranslator.FromState(luaState); IReflect klass; object obj = translator.getRawNetObject(luaState, 1); if (obj == null || !(obj is IReflect)) { translator.throwError(luaState, "trying to index an invalid type reference"); LuaDLL.lua_pushnil(luaState); return(1); } else { klass = (IReflect)obj; } if (LuaDLL.lua_isnumber(luaState, 2)) { int size = (int)LuaDLL.lua_tonumber(luaState, 2); translator.push(luaState, Array.CreateInstance(klass.UnderlyingSystemType, size)); return(1); } else { string methodName = LuaDLL.lua_tostring(luaState, 2); if (methodName == null) { LuaDLL.lua_pushnil(luaState); return(1); } //CP: Ignore case else { return(translator.metaFunctions.getMember(luaState, klass, null, methodName, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.IgnoreCase)); } } }
/* * Pushes the value of a member or a delegate to call it, depending on the type of * the member. Works with static or instance members. * Uses reflection to find members, and stores the reflected MemberInfo object in * a cache (indexed by the type of the object and the name of the member). */ private int getMember(IntPtr luaState, IReflect objType, object obj, string methodName, BindingFlags bindingType) { bool implicitStatic = false; MemberInfo member = null; object cachedMember = checkMemberCache(memberCache, objType, methodName); //object cachedMember=null; if (cachedMember is LuaCSFunction) { translator.pushFunction(luaState, (LuaCSFunction)cachedMember); translator.push(luaState, true); return(2); } else if (cachedMember != null) { member = (MemberInfo)cachedMember; } else { //CP: Removed NonPublic binding search MemberInfo[] members = objType.GetMember(methodName, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase /*| BindingFlags.NonPublic*/); if (members.Length > 0) { member = members[0]; } else { // If we can't find any suitable instance members, try to find them as statics - but we only want to allow implicit static // lookups for fields/properties/events -kevinh //CP: Removed NonPublic binding search and made case insensitive members = objType.GetMember(methodName, bindingType | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase /*| BindingFlags.NonPublic*/); if (members.Length > 0) { member = members[0]; implicitStatic = true; } } } if (member != null) { if (member.MemberType == MemberTypes.Field) { FieldInfo field = (FieldInfo)member; if (cachedMember == null) { setMemberCache(memberCache, objType, methodName, member); } try { translator.push(luaState, field.GetValue(obj)); } catch { LuaDLL.lua_pushnil(luaState); } } else if (member.MemberType == MemberTypes.Property) { PropertyInfo property = (PropertyInfo)member; if (cachedMember == null) { setMemberCache(memberCache, objType, methodName, member); } try { object val = property.GetValue(obj, null); translator.push(luaState, val); } catch (ArgumentException) { // If we can't find the getter in our class, recurse up to the base class and see // if they can help. if (objType is Type && !(((Type)objType) == typeof(object))) { return(getMember(luaState, ((Type)objType).BaseType, obj, methodName, bindingType)); } else { LuaDLL.lua_pushnil(luaState); } } catch (TargetInvocationException e) // Convert this exception into a Lua error { ThrowError(luaState, e); LuaDLL.lua_pushnil(luaState); } } else if (member.MemberType == MemberTypes.Event) { EventInfo eventInfo = (EventInfo)member; if (cachedMember == null) { setMemberCache(memberCache, objType, methodName, member); } translator.push(luaState, new RegisterEventHandler(translator.pendingEvents, obj, eventInfo)); } else if (!implicitStatic) { if (member.MemberType == MemberTypes.NestedType) { // kevinh - added support for finding nested types // cache us if (cachedMember == null) { setMemberCache(memberCache, objType, methodName, member); } // Find the name of our class string name = member.Name; Type dectype = member.DeclaringType; // Build a new long name and try to find the type by name string longname = dectype.FullName + "+" + name; Type nestedType = translator.FindType(longname); translator.pushType(luaState, nestedType); } else { // Member type must be 'method' LuaCSFunction wrapper = new LuaCSFunction((new LuaMethodWrapper(translator, objType, methodName, bindingType)).call); if (cachedMember == null) { setMemberCache(memberCache, objType, methodName, wrapper); } translator.pushFunction(luaState, wrapper); translator.push(luaState, true); return(2); } } else { // If we reach this point we found a static method, but can't use it in this context because the user passed in an instance translator.throwError(luaState, "can't pass instance to static method " + methodName); LuaDLL.lua_pushnil(luaState); } } else { // kevinh - we want to throw an exception because meerly returning 'nil' in this case // is not sufficient. valid data members may return nil and therefore there must be some // way to know the member just doesn't exist. translator.throwError(luaState, "unknown member name " + methodName); LuaDLL.lua_pushnil(luaState); } // push false because we are NOT returning a function (see luaIndexFunction) translator.push(luaState, false); return(2); }
/* * Calls the method. Receives the arguments from the Lua stack * and returns values in it. */ public int call(KopiLua.Lua.lua_State luaState) { MethodBase methodToCall = _Method; object targetObject = _Target; bool failedCall = true; int nReturnValues = 0; if (!LuaDLL.lua_checkstack(luaState, 5)) { throw new LuaException("Lua stack overflow"); } bool isStatic = (_BindingType & BindingFlags.Static) == BindingFlags.Static; SetPendingException(null); if (methodToCall == null) // Method from name { if (isStatic) { targetObject = null; } else { targetObject = _ExtractTarget(luaState, 1); } //LuaDLL.lua_remove(luaState,1); // Pops the receiver 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 = LuaDLL.lua_gettop(luaState) - numStackToSkip; MethodBase method = _LastCalledMethod.cachedMethod; if (numArgsPassed == _LastCalledMethod.argTypes.Length) // No. of args match? { if (!LuaDLL.lua_checkstack(luaState, _LastCalledMethod.outList.Length + 6)) { throw new LuaException("Lua stack overflow"); } 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 && !LuaDLL.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) { // Failure of method invocation return(SetPendingException(e.GetBaseException())); } catch (Exception e) { if (_Members.Length == 1) // Is the method overloaded? // No, throw error { return(SetPendingException(e)); } } } } // Cache miss if (failedCall) { // System.Diagnostics.Debug.WriteLine("cache miss on " + methodName); // If we are running an instance variable, we can now pop the targetObject from the stack if (!isStatic) { if (targetObject == null) { _Translator.throwError(luaState, String.Format("instance method '{0}' requires a non null target object", _MethodName)); LuaDLL.lua_pushnil(luaState); return(1); } LuaDLL.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); _Translator.throwError(luaState, msg); LuaDLL.lua_pushnil(luaState); return(1); } } } else // Method from MethodBase instance { if (methodToCall.ContainsGenericParameters) { // bool isMethod = //* not used _Translator.matchParameters(luaState, methodToCall, ref _LastCalledMethod); if (methodToCall.IsGenericMethodDefinition) { //need to make a concrete type of the generic method definition List <Type> typeArgs = new List <Type>(); foreach (object arg in _LastCalledMethod.args) { typeArgs.Add(arg.GetType()); } MethodInfo concreteMethod = (methodToCall as MethodInfo).MakeGenericMethod(typeArgs.ToArray()); _Translator.push(luaState, concreteMethod.Invoke(targetObject, _LastCalledMethod.args)); failedCall = false; } else if (methodToCall.ContainsGenericParameters) { _Translator.throwError(luaState, "unable to invoke method on generic class as the current method is an open generic method"); LuaDLL.lua_pushnil(luaState); return(1); } } else { if (!methodToCall.IsStatic && !methodToCall.IsConstructor && targetObject == null) { targetObject = _ExtractTarget(luaState, 1); LuaDLL.lua_remove(luaState, 1); // Pops the receiver } if (!_Translator.matchParameters(luaState, methodToCall, ref _LastCalledMethod)) { _Translator.throwError(luaState, "invalid arguments to method call"); LuaDLL.lua_pushnil(luaState); return(1); } } } if (failedCall) { if (!LuaDLL.lua_checkstack(luaState, _LastCalledMethod.outList.Length + 6)) { 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) { return(SetPendingException(e.GetBaseException())); } catch (Exception e) { 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]]); } //by isSingle 2010-09-10 11:26:31 //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++; } return(nReturnValues < 1 ? 1 : nReturnValues); }
/// <summary>Calls the method. Receives the arguments from the Lua stack and returns values in it.</summary> public int call(lua.State L) { using (luanet.entercfunction(L, _Translator.interpreter)) { MethodBase methodToCall = _Method; object targetObject = _Target; bool failedCall = true; int nReturnValues = 0; luaL.checkstack(L, 5, "MethodWrapper.call"); bool isStatic = (_BindingType & BindingFlags.Static) == BindingFlags.Static; if (methodToCall == null) // Method from name { targetObject = isStatic ? null : _ExtractTarget(L, 1); //lua.remove(L,1); // Pops the receiver if (_LastCalledMethod.cachedMethod != null && _Translator.memberIsAllowed(_LastCalledMethod.cachedMethod)) // 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 = lua.gettop(L) - numStackToSkip; MethodBase method = _LastCalledMethod.cachedMethod; if (numArgsPassed == _LastCalledMethod.argTypes.Length) // No. of args match? { luaL.checkstack(L, _LastCalledMethod.outList.Length + 6, "MethodWrapper.call"); object[] args = _LastCalledMethod.args; try { for (int i = 0; i < _LastCalledMethod.argTypes.Length; i++) { MethodArgs type = _LastCalledMethod.argTypes[i]; object luaParamValue = type.extractValue(L, i + 1 + numStackToSkip); args[type.index] = _LastCalledMethod.argTypes[i].isParamsArray ? ObjectTranslator.TableToArray(luaParamValue, type.paramsArrayType) : luaParamValue; if (args[type.index] == null && !lua.isnil(L, i + 1 + numStackToSkip)) { throw new LuaException("argument number " + (i + 1) + " is invalid"); } } _Translator.pushReturnValue(L, method.IsConstructor ? ((ConstructorInfo)method).Invoke(args) : method.Invoke(targetObject, args)); failedCall = false; } catch (TargetInvocationException ex) { return(_Translator.throwError(L, luaclr.verifyex(ex.InnerException))); } catch (LuaInternalException) { throw; } catch (Exception ex) { if (_Members.Length == 1) // Is the method overloaded? { return(luaL.error(L, "method call failed ({0})", ex.Message)); // No, throw error } } } } // Cache miss if (failedCall) { // System.Diagnostics.Debug.WriteLine("cache miss on " + methodName); // If we are running an instance variable, we can now pop the targetObject from the stack if (!isStatic) { if (targetObject == null) { return(luaL.error(L, String.Format("instance method '{0}' requires a non null target object", _MethodName))); } lua.remove(L, 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(L, m, ref _LastCalledMethod); if (isMethod) { if (_Translator.memberIsAllowed(member)) { hasMatch = true; break; } if (_Members.Length == 1) { return(luaL.error(L, "method call failed (access denied)")); } } } if (!hasMatch) { return(luaL.error(L, (candidateName == null) ? "invalid arguments to method call" : "invalid arguments to method: " + candidateName)); } } } else // Method from MethodBase instance { if (!_Translator.memberIsAllowed(methodToCall)) { return(luaL.error(L, "method call failed (access denied)")); } if (methodToCall.ContainsGenericParameters) { // bool isMethod = //* not used _Translator.matchParameters(L, methodToCall, ref _LastCalledMethod); if (methodToCall.IsGenericMethodDefinition) { //need to make a concrete type of the generic method definition var args = _LastCalledMethod.args; var typeArgs = new Type[args.Length]; for (int i = 0; i < args.Length; ++i) { typeArgs[i] = args[i].GetType(); } MethodInfo concreteMethod = ((MethodInfo)methodToCall).MakeGenericMethod(typeArgs); _Translator.pushReturnValue(L, concreteMethod.Invoke(targetObject, args)); failedCall = false; } else if (methodToCall.ContainsGenericParameters) { return(luaL.error(L, "unable to invoke method on generic class as the current method is an open generic method")); } } else { if (!methodToCall.IsStatic && !methodToCall.IsConstructor && targetObject == null) { targetObject = _ExtractTarget(L, 1); lua.remove(L, 1); // Pops the receiver } if (!_Translator.matchParameters(L, methodToCall, ref _LastCalledMethod)) { return(luaL.error(L, "invalid arguments to method call")); } } } if (failedCall) { if (!_Translator.memberIsAllowed(_LastCalledMethod.cachedMethod)) { return(luaL.error(L, "method call failed (access denied)")); } luaL.checkstack(L, _LastCalledMethod.outList.Length + 6, "MethodWrapper.call"); try { _Translator.pushReturnValue(L, _LastCalledMethod.cachedMethod.IsConstructor ? ((ConstructorInfo)_LastCalledMethod.cachedMethod).Invoke(_LastCalledMethod.args) : _LastCalledMethod.cachedMethod.Invoke(isStatic ? null : targetObject, _LastCalledMethod.args)); } catch (TargetInvocationException ex) { return(_Translator.throwError(L, luaclr.verifyex(ex.InnerException))); } catch (LuaInternalException) { throw; } catch (Exception ex) { return(luaL.error(L, "method call failed ({0})", ex.Message)); } } // Pushes out and ref return values foreach (int arg in _LastCalledMethod.outList) { nReturnValues++; _Translator.pushReturnValue(L, _LastCalledMethod.args[arg]); } //by isSingle 2010-09-10 11:26:31 //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++; } return(nReturnValues < 1 ? 1 : nReturnValues); } }
public static int getMethod(IntPtr luaState) { ObjectTranslator translator = ObjectTranslator.FromState(luaState); object obj = translator.getRawNetObject(luaState, 1); if (obj == null) { translator.throwError(luaState, "trying to index an invalid object reference"); LuaDLL.lua_pushnil(luaState); return(1); } object index = translator.getObject(luaState, 2); //Type indexType = index.GetType(); //* not used string methodName = index as string; // will be null if not a string arg Type objType = obj.GetType(); // Handle the most common case, looking up the method by name. // CP: This will fail when using indexers and attempting to get a value with the same name as a property of the object, // ie: xmlelement['item'] <- item is a property of xmlelement try { if (methodName != null && translator.metaFunctions.isMemberPresent(objType, methodName)) { return(translator.metaFunctions.getMember(luaState, objType, obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase)); } } catch { } bool failed = true; // Try to access by array if the type is right and index is an int (lua numbers always come across as double) if (objType.IsArray && index is double) { int intIndex = (int)((double)index); Array aa = obj as Array; if (intIndex >= aa.Length) { return(translator.pushError(luaState, "array index out of bounds: " + intIndex + " " + aa.Length)); } object val = aa.GetValue(intIndex); translator.push(luaState, val); failed = false; } else { // Try to use get_Item to index into this .net object //MethodInfo getter = objType.GetMethod("get_Item"); // issue here is that there may be multiple indexers.. MethodInfo[] methods = objType.GetMethods(); foreach (MethodInfo mInfo in methods) { if (mInfo.Name == "get_Item") { //check if the signature matches the input if (mInfo.GetParameters().Length == 1) { MethodInfo getter = mInfo; ParameterInfo[] actualParms = (getter != null) ? getter.GetParameters() : null; if (actualParms == null || actualParms.Length != 1) { return(translator.pushError(luaState, "method not found (or no indexer): " + index)); } else { // Get the index in a form acceptable to the getter index = translator.getAsType(luaState, 2, actualParms[0].ParameterType); // Just call the indexer - if out of bounds an exception will happen try { object result = getter.Invoke(obj, new object[] { index }); translator.push(luaState, result); failed = false; } catch (TargetInvocationException e) { // Provide a more readable description for the common case of key not found if (e.InnerException is KeyNotFoundException) { return(translator.pushError(luaState, "key '" + index + "' not found ")); } else { return(translator.pushError(luaState, "exception indexing '" + index + "' " + e.Message)); } } } } } } } if (failed) { return(translator.pushError(luaState, "cannot find " + index)); } LuaDLL.lua_pushboolean(luaState, false); return(2); }
public static int setFieldOrProperty(IntPtr luaState) { ObjectTranslator translator = ObjectTranslator.FromState(luaState); object target = translator.getRawNetObject(luaState, 1); if (target == null) { translator.throwError(luaState, "trying to index and invalid object reference"); return(0); } Type type = target.GetType(); // First try to look up the parameter as a property name string detailMessage; bool didMember = translator.metaFunctions.trySetMember(luaState, type, target, BindingFlags.Instance | BindingFlags.IgnoreCase, out detailMessage); if (didMember) { return(0); // Must have found the property name } // We didn't find a property name, now see if we can use a [] style this accessor to set array contents try { if (type.IsArray && LuaDLL.lua_isnumber(luaState, 2)) { int index = (int)LuaDLL.lua_tonumber(luaState, 2); Array arr = (Array)target; object val = translator.getAsType(luaState, 3, arr.GetType().GetElementType()); arr.SetValue(val, index); } else { // Try to see if we have a this[] accessor MethodInfo setter = type.GetMethod("set_Item"); if (setter != null) { ParameterInfo[] args = setter.GetParameters(); Type valueType = args[1].ParameterType; // The new val ue the user specified object val = translator.getAsType(luaState, 3, valueType); Type indexType = args[0].ParameterType; object index = translator.getAsType(luaState, 2, indexType); object[] methodArgs = new object[2]; // Just call the indexer - if out of bounds an exception will happen methodArgs[0] = index; methodArgs[1] = val; setter.Invoke(target, methodArgs); } else { translator.throwError(luaState, detailMessage); // Pass the original message from trySetMember because it is probably best } } } catch (SEHException) { // If we are seeing a C++ exception - this must actually be for Lua's private use. Let it handle it throw; } catch (Exception e) { translator.metaFunctions.ThrowError(luaState, e); } return(0); }
/* * Called by the __index metafunction of CLR objects in case the * method is not cached or it is a field/property/event. * Receives the object and the member name as arguments and returns * either the value of the member or a delegate to call it. * If the member does not exist returns nil. */ private int getMethod(KopiLua.Lua.lua_State luaState) { object obj = translator.getRawNetObject(luaState, 1); if (obj == null) { translator.throwError(luaState, "trying to index an invalid object reference"); LuaDLL.lua_pushnil(luaState); return(1); } object index = translator.getObject(luaState, 2); Type indexType = index.GetType(); string methodName = index as string; // will be null if not a string arg Type objType = obj.GetType(); // Handle the most common case, looking up the method by name if (methodName != null && isMemberPresent(objType, methodName)) { return(getMember(luaState, objType, obj, methodName, BindingFlags.Instance)); } // Try to access by array if the type is right and index is an int (lua numbers always come across as double) if (objType.IsArray && index is double) { object[] arr = (object[])obj; translator.push(luaState, arr[(int)((double)index)]); } else { // Try to use get_Item to index into this .net object MethodInfo getter = objType.GetMethod("get_Item"); ParameterInfo[] actualParms = (getter != null) ? getter.GetParameters() : null; if (actualParms == null || actualParms.Length != 1) { translator.throwError(luaState, "method not found (or no indexer): " + index); LuaDLL.lua_pushnil(luaState); } else { // Get the index in a form acceptable to the getter index = translator.getAsType(luaState, 2, actualParms[0].ParameterType); object[] args = new object[1]; // Just call the indexer - if out of bounds an exception will happen args[0] = index; try { object result = getter.Invoke(obj, args); translator.push(luaState, result); } catch (TargetInvocationException e) { // Provide a more readable description for the common case of key not found if (e.InnerException is KeyNotFoundException) { translator.throwError(luaState, "key '" + index + "' not found "); } else { translator.throwError(luaState, "exception indexing '" + index + "' " + e.Message); } LuaDLL.lua_pushnil(luaState); } } } LuaDLL.lua_pushboolean(luaState, false); return(2); }
/* * Called by the __index metafunction of CLR objects in case the * method is not cached or it is a field/property/event. * Receives the object and the member name as arguments and returns * either the value of the member or a delegate to call it. * If the member does not exist returns nil. */ private int getMethod(IntPtr luaState) { object obj = translator.getRawNetObject(luaState, 1); if (obj == null) { translator.throwError(luaState, "trying to index an invalid object reference"); LuaDLL.lua_pushnil(luaState); return(1); } object index = translator.getObject(luaState, 2); Type indexType = index.GetType(); string methodName = index as string; // will be null if not a string arg Type objType = obj.GetType(); // Handle the most common case, looking up the method by name. // CP: This will fail when using indexers and attempting to get a value with the same name as a property of the object, // ie: xmlelement['item'] <- item is a property of xmlelement try { if (methodName != null && isMemberPresent(objType, methodName)) { return(getMember(luaState, objType, obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase)); } } catch { } // Try to access by array if the type is right and index is an int (lua numbers always come across as double) if (objType.IsArray && index is double) { int intIndex = (int)((double)index); if (objType.UnderlyingSystemType == typeof(float[])) { float[] arr = ((float[])obj); translator.push(luaState, arr[intIndex]); } else if (objType.UnderlyingSystemType == typeof(double[])) { double[] arr = ((double[])obj); translator.push(luaState, arr[intIndex]); } else if (objType.UnderlyingSystemType == typeof(int[])) { int[] arr = ((int[])obj); translator.push(luaState, arr[intIndex]); } else { object[] arr = (object[])obj; translator.push(luaState, arr[intIndex]); } } else { // Try to use get_Item to index into this .net object //MethodInfo getter = objType.GetMethod("get_Item"); MethodInfo[] methods = objType.GetMethods(); foreach (MethodInfo mInfo in methods) { if (mInfo.Name == "get_Item") { //check if the signature matches the input if (mInfo.GetParameters().Length == 1) { MethodInfo getter = mInfo; ParameterInfo[] actualParms = (getter != null) ? getter.GetParameters() : null; if (actualParms == null || actualParms.Length != 1) { translator.throwError(luaState, "method not found (or no indexer): " + index); LuaDLL.lua_pushnil(luaState); } else { // Get the index in a form acceptable to the getter index = translator.getAsType(luaState, 2, actualParms[0].ParameterType); object[] args = new object[1]; // Just call the indexer - if out of bounds an exception will happen args[0] = index; try { object result = getter.Invoke(obj, args); translator.push(luaState, result); } catch (TargetInvocationException e) { // Provide a more readable description for the common case of key not found if (e.InnerException is KeyNotFoundException) { translator.throwError(luaState, "key '" + index + "' not found "); } else { translator.throwError(luaState, "exception indexing '" + index + "' " + e.Message); } LuaDLL.lua_pushnil(luaState); } } } } } } LuaDLL.lua_pushboolean(luaState, false); return(2); }
internal ExtractValue checkType(IntPtr luaState, int stackPos, Type paramType) { LuaTypes luatype = LuaDLL.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()]); } //else // suppress CS0642 ; //an unsupported type was encountered } if (paramType.IsValueType && luatype == LuaTypes.LUA_TTABLE) { int oldTop = LuaDLL.lua_gettop(luaState); ExtractValue ret = null; LuaDLL.lua_pushvalue(luaState, stackPos); LuaDLL.lua_pushstring(luaState, "class"); LuaDLL.lua_gettable(luaState, -2); if (!LuaDLL.lua_isnil(luaState, -1)) { string cls = LuaDLL.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; } } LuaDLL.lua_settop(luaState, oldTop); if (ret != null) { return(ret); } } if (LuaDLL.lua_isnumber(luaState, stackPos)) { return(extractValues[runtimeHandleValue]); } if (paramType == typeof(bool)) { if (LuaDLL.lua_isboolean(luaState, stackPos)) { return(extractValues[runtimeHandleValue]); } } else if (paramType == typeof(string)) { if (LuaDLL.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) { #if __NOGEN__ translator.throwError(luaState, "Delegates not implemnented"); #else return(new ExtractValue(new DelegateGenerator(translator, paramType).extractGenerated)); #endif } else if (paramType.IsInterface && luatype == LuaTypes.LUA_TTABLE) { #if __NOGEN__ translator.throwError(luaState, "Interfaces not implemnented"); #else return(new ExtractValue(new ClassGenerator(translator, paramType).extractGenerated)); #endif } 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 (LuaDLL.lua_type(luaState, stackPos) == LuaTypes.LUA_TTABLE) { if (LuaTypes.LUA_TNIL != LuaDLL.luaL_getmetafield(luaState, stackPos, "__index")) { object obj = translator.getNetObject(luaState, -1); LuaDLL.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); }