public static int Cast(RealStatePtr L) { try { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); Type type; translator.Get(L, 2, out type); if (type == null) { return(LuaAPI.luaL_error(L, "#2 param[" + LuaAPI.lua_tostring(L, 2) + "]is not valid type indicator")); } LuaAPI.luaL_getmetatable(L, type.FullName); if (LuaAPI.lua_isnil(L, -1)) { return(LuaAPI.luaL_error(L, "no gen code for " + LuaAPI.lua_tostring(L, 2))); } LuaAPI.lua_setmetatable(L, 1); return(0); } catch (System.Exception e) { return(LuaAPI.luaL_error(L, "c# exception in xlua.cast:" + e)); } }
int getTypeId(RealStatePtr L, Type type, out bool is_first, LOGLEVEL log_level = LOGLEVEL.WARN) { int type_id; is_first = false; if (!typeIdMap.TryGetValue(type, out type_id)) // no reference { if (type.IsArray) { if (common_array_meta == -1) throw new Exception("Fatal Exception! Array Metatable not inited!"); return common_array_meta; } if (typeof(MulticastDelegate).IsAssignableFrom(type)) { if (common_delegate_meta == -1) throw new Exception("Fatal Exception! Delegate Metatable not inited!"); return common_delegate_meta; } is_first = true; Type alias_type = null; aliasCfg.TryGetValue(type, out alias_type); LuaAPI.luaL_getmetatable(L, alias_type == null ? type.FullName : alias_type.FullName); if (LuaAPI.lua_isnil(L, -1)) //no meta yet, try to use reflection meta { LuaAPI.lua_pop(L, 1); if (TryDelayWrapLoader(L, alias_type == null ? type : alias_type)) { LuaAPI.luaL_getmetatable(L, alias_type == null ? type.FullName : alias_type.FullName); } else { throw new Exception("Fatal: can not load metatable of type:" + type); } } //循环依赖,自身依赖自己的class,比如有个自身类型的静态readonly对象。 if (typeIdMap.TryGetValue(type, out type_id)) { LuaAPI.lua_pop(L, 1); } else { LuaAPI.lua_pushvalue(L, -1); type_id = LuaAPI.luaL_ref(L, LuaIndexes.LUA_REGISTRYINDEX); LuaAPI.lua_pushnumber(L, type_id); LuaAPI.xlua_rawseti(L, -2, 1); LuaAPI.lua_pop(L, 1); if (type.IsValueType) { typeMap.Add(type_id, type); } typeIdMap.Add(type, type_id); } } return type_id; }
public static void BeginObjectRegister(Type type, RealStatePtr L, ObjectTranslator translator, int meta_count, int method_count, int getter_count, int setter_count, int type_id = -1) { if (type == null) { if (type_id == -1) { throw new Exception("Fatal: must provide a type of type_id"); } LuaAPI.xlua_rawgeti(L, LuaIndexes.LUA_REGISTRYINDEX, type_id); } else { LuaAPI.luaL_getmetatable(L, type.FullName); } }
public static void MakePrivateAccessible(RealStatePtr L, Type type) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); int oldTop = LuaAPI.lua_gettop(L); LuaAPI.luaL_getmetatable(L, type.FullName); if (LuaAPI.lua_isnil(L, -1)) { LuaAPI.lua_settop(L, oldTop); throw new Exception("can not find the metatable for " + type); } int obj_meta = LuaAPI.lua_gettop(L); LoadCSTable(L, type); if (LuaAPI.lua_isnil(L, -1)) { LuaAPI.lua_settop(L, oldTop); throw new Exception("can not find the class for " + type); } int cls_field = LuaAPI.lua_gettop(L); loadUpvalue(L, type, Utils.LuaIndexsFieldName, 2); int obj_getter = LuaAPI.lua_gettop(L); int obj_field = obj_getter - 1; loadUpvalue(L, type, Utils.LuaNewIndexsFieldName, 1); int obj_setter = LuaAPI.lua_gettop(L); loadUpvalue(L, type, Utils.LuaClassIndexsFieldName, 1); int cls_getter = LuaAPI.lua_gettop(L); loadUpvalue(L, type, Utils.LuaClassNewIndexsFieldName, 1); int cls_setter = LuaAPI.lua_gettop(L); LuaCSFunction item_getter; LuaCSFunction item_setter; makeReflectionWrap(L, type, cls_field, cls_getter, cls_setter, obj_field, obj_getter, obj_setter, obj_meta, out item_getter, out item_setter, true); LuaAPI.lua_settop(L, oldTop); }
//meta: -4, method:-3, getter: -2, setter: -1 public static void BeginObjectRegister(Type type, RealStatePtr L, ObjectTranslator translator, int meta_count, int method_count, int getter_count, int setter_count, int type_id = -1) { if (type == null) { if (type_id == -1) { throw new Exception("Fatal: must provide a type of type_id"); } LuaAPI.xlua_rawgeti(L, LuaIndexes.LUA_REGISTRYINDEX, type_id); } else { LuaAPI.luaL_getmetatable(L, type.FullName); if (LuaAPI.lua_isnil(L, -1)) { LuaAPI.lua_pop(L, 1); LuaAPI.luaL_newmetatable(L, type.FullName); } } LuaAPI.lua_pushlightuserdata(L, LuaAPI.xlua_tag()); LuaAPI.lua_pushnumber(L, 1); LuaAPI.lua_rawset(L, -3); if ((type == null || !translator.HasCustomOp(type)) && type != typeof(decimal)) { LuaAPI.xlua_pushasciistring(L, "__gc"); LuaAPI.lua_pushstdcallcfunction(L, translator.metaFunctions.GcMeta); LuaAPI.lua_rawset(L, -3); } LuaAPI.xlua_pushasciistring(L, "__tostring"); LuaAPI.lua_pushstdcallcfunction(L, translator.metaFunctions.ToStringMeta); LuaAPI.lua_rawset(L, -3); if (method_count == 0) { LuaAPI.lua_pushnil(L); } else { LuaAPI.lua_createtable(L, 0, method_count); } if (getter_count == 0) { LuaAPI.lua_pushnil(L); } else { LuaAPI.lua_createtable(L, 0, getter_count); } if (setter_count == 0) { LuaAPI.lua_pushnil(L); } else { LuaAPI.lua_createtable(L, 0, setter_count); } }
public static void ReflectionWrap(RealStatePtr L, Type type) { int top_enter = LuaAPI.lua_gettop(L); ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); //create obj meta table LuaAPI.luaL_getmetatable(L, type.FullName); if (LuaAPI.lua_isnil(L, -1)) { LuaAPI.lua_pop(L, 1); LuaAPI.luaL_newmetatable(L, type.FullName); } LuaAPI.lua_pushlightuserdata(L, LuaAPI.xlua_tag()); LuaAPI.lua_pushnumber(L, 1); LuaAPI.lua_rawset(L, -3); int obj_meta = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int cls_meta = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int obj_field = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int obj_getter = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int obj_setter = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int cls_field = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int cls_getter = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int cls_setter = LuaAPI.lua_gettop(L); LuaCSFunction item_getter; LuaCSFunction item_setter; makeReflectionWrap(L, type, cls_field, cls_getter, cls_setter, obj_field, obj_getter, obj_setter, obj_meta, out item_getter, out item_setter); // init obj metatable LuaAPI.xlua_pushasciistring(L, "__gc"); LuaAPI.lua_pushstdcallcfunction(L, translator.metaFunctions.GcMeta); LuaAPI.lua_rawset(L, obj_meta); LuaAPI.xlua_pushasciistring(L, "__tostring"); LuaAPI.lua_pushstdcallcfunction(L, translator.metaFunctions.ToStringMeta); LuaAPI.lua_rawset(L, obj_meta); LuaAPI.xlua_pushasciistring(L, "__index"); LuaAPI.lua_pushvalue(L, obj_field); LuaAPI.lua_pushvalue(L, obj_getter); translator.PushFixCSFunction(L, item_getter); translator.PushAny(L, type.BaseType); LuaAPI.xlua_pushasciistring(L, Utils.LuaIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); LuaAPI.lua_pushnil(L); LuaAPI.gen_obj_indexer(L); //store in lua indexs function tables LuaAPI.xlua_pushasciistring(L, Utils.LuaIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); translator.Push(L, type); LuaAPI.lua_pushvalue(L, -3); LuaAPI.lua_rawset(L, -3); LuaAPI.lua_pop(L, 1); LuaAPI.lua_rawset(L, obj_meta); // set __index LuaAPI.xlua_pushasciistring(L, "__newindex"); LuaAPI.lua_pushvalue(L, obj_setter); translator.PushFixCSFunction(L, item_setter); translator.Push(L, type.BaseType); LuaAPI.xlua_pushasciistring(L, Utils.LuaNewIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); LuaAPI.lua_pushnil(L); LuaAPI.gen_obj_newindexer(L); //store in lua newindexs function tables LuaAPI.xlua_pushasciistring(L, Utils.LuaNewIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); translator.Push(L, type); LuaAPI.lua_pushvalue(L, -3); LuaAPI.lua_rawset(L, -3); LuaAPI.lua_pop(L, 1); LuaAPI.lua_rawset(L, obj_meta); // set __newindex //finish init obj metatable LuaAPI.xlua_pushasciistring(L, "UnderlyingSystemType"); translator.PushAny(L, type); LuaAPI.lua_rawset(L, cls_field); if (type != null && type.IsEnum) { LuaAPI.xlua_pushasciistring(L, "__CastFrom"); translator.PushFixCSFunction(L, genEnumCastFrom(type)); LuaAPI.lua_rawset(L, cls_field); } //set cls_field to namespace SetCSTable(L, type, cls_field); //finish set cls_field to namespace //init class meta LuaAPI.xlua_pushasciistring(L, "__index"); LuaAPI.lua_pushvalue(L, cls_getter); LuaAPI.lua_pushvalue(L, cls_field); translator.Push(L, type.BaseType); LuaAPI.xlua_pushasciistring(L, Utils.LuaClassIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); LuaAPI.gen_cls_indexer(L); //store in lua indexs function tables LuaAPI.xlua_pushasciistring(L, Utils.LuaClassIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); translator.Push(L, type); LuaAPI.lua_pushvalue(L, -3); LuaAPI.lua_rawset(L, -3); LuaAPI.lua_pop(L, 1); LuaAPI.lua_rawset(L, cls_meta); // set __index LuaAPI.xlua_pushasciistring(L, "__newindex"); LuaAPI.lua_pushvalue(L, cls_setter); translator.Push(L, type.BaseType); LuaAPI.xlua_pushasciistring(L, Utils.LuaClassNewIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); LuaAPI.gen_cls_newindexer(L); //store in lua newindexs function tables LuaAPI.xlua_pushasciistring(L, Utils.LuaClassNewIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); translator.Push(L, type); LuaAPI.lua_pushvalue(L, -3); LuaAPI.lua_rawset(L, -3); LuaAPI.lua_pop(L, 1); LuaAPI.lua_rawset(L, cls_meta); // set __newindex LuaCSFunction constructor = translator.methodWrapsCache.GetConstructorWrap(type); if (constructor == null) { constructor = (RealStatePtr LL) => { return(LuaAPI.luaL_error(LL, "No constructor for " + type)); }; } LuaAPI.xlua_pushasciistring(L, "__call"); translator.PushFixCSFunction(L, constructor); LuaAPI.lua_rawset(L, cls_meta); LuaAPI.lua_pushvalue(L, cls_meta); LuaAPI.lua_setmetatable(L, cls_field); LuaAPI.lua_pop(L, 8); System.Diagnostics.Debug.Assert(top_enter == LuaAPI.lua_gettop(L)); }
public static void ReflectionWrap(RealStatePtr L, Type type) { int top_enter = LuaAPI.lua_gettop(L); ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); //create obj meta table LuaAPI.luaL_getmetatable(L, type.FullName); if (LuaAPI.lua_isnil(L, -1)) { LuaAPI.lua_pop(L, 1); LuaAPI.luaL_newmetatable(L, type.FullName); } LuaAPI.lua_pushlightuserdata(L, LuaAPI.xlua_tag()); LuaAPI.lua_pushnumber(L, 1); LuaAPI.lua_rawset(L, -3); int obj_meta = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int cls_meta = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int obj_field = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int obj_getter = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int obj_setter = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int cls_field = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int cls_getter = LuaAPI.lua_gettop(L); LuaAPI.lua_newtable(L); int cls_setter = LuaAPI.lua_gettop(L); BindingFlags flag = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; FieldInfo[] fields = type.GetFields(flag); for (int i = 0; i < fields.Length; ++i) { FieldInfo field = fields[i]; if (field.IsStatic && (field.IsInitOnly || field.IsLiteral)) { LuaAPI.xlua_pushasciistring(L, field.Name); translator.PushAny(L, field.GetValue(null)); LuaAPI.lua_rawset(L, cls_field); } else { LuaAPI.xlua_pushasciistring(L, field.Name); translator.PushFixCSFunction(L, genFieldGetter(type, field)); LuaAPI.lua_rawset(L, field.IsStatic ? cls_getter : obj_getter); LuaAPI.xlua_pushasciistring(L, field.Name); translator.PushFixCSFunction(L, genFieldSetter(type, field)); LuaAPI.lua_rawset(L, field.IsStatic ? cls_setter : obj_setter); } } EventInfo[] events = type.GetEvents(flag); for (int i = 0; i < events.Length; ++i) { EventInfo eventInfo = events[i]; LuaAPI.xlua_pushasciistring(L, eventInfo.Name); translator.PushFixCSFunction(L, translator.methodWrapsCache.GetEventWrap(type, eventInfo.Name)); bool is_static = (eventInfo.GetAddMethod() != null) ? eventInfo.GetAddMethod().IsStatic : eventInfo.GetRemoveMethod().IsStatic; LuaAPI.lua_rawset(L, is_static ? cls_field : obj_field); } Dictionary <string, PropertyInfo> prop_map = new Dictionary <string, PropertyInfo>(); List <PropertyInfo> items = new List <PropertyInfo>(); PropertyInfo[] props = type.GetProperties(flag); for (int i = 0; i < props.Length; ++i) { PropertyInfo prop = props[i]; if (prop.Name == "Item") { items.Add(prop); } else { prop_map.Add(prop.Name, prop); } } var item_array = items.ToArray(); LuaCSFunction item_getter = item_array.Length > 0 ? genItemGetter(type, item_array) : null; LuaCSFunction item_setter = item_array.Length > 0 ? genItemSetter(type, item_array) : null;; MethodInfo[] methods = type.GetMethods(flag); Dictionary <MethodKey, List <MemberInfo> > pending_methods = new Dictionary <MethodKey, List <MemberInfo> >(); for (int i = 0; i < methods.Length; ++i) { MethodInfo method = methods[i]; string method_name = method.Name; MethodKey method_key = new MethodKey { Name = method_name, IsStatic = method.IsStatic }; List <MemberInfo> overloads; if (pending_methods.TryGetValue(method_key, out overloads)) { overloads.Add(method); continue; } PropertyInfo prop = null; if (method_name.StartsWith("add_") || method_name.StartsWith("remove_") || method_name == "get_Item" || method_name == "set_Item") { continue; } if (method_name.StartsWith("op_")) // 操作符 { if (support_op.ContainsKey(method_name)) { if (overloads == null) { overloads = new List <MemberInfo>(); pending_methods.Add(method_key, overloads); } overloads.Add(method); } continue; } else if (method_name.StartsWith("get_") && prop_map.TryGetValue(method.Name.Substring(4), out prop)) // getter of property { LuaAPI.xlua_pushasciistring(L, prop.Name); translator.PushFixCSFunction(L, genPropGetter(type, prop, method.IsStatic)); LuaAPI.lua_rawset(L, method.IsStatic ? cls_getter : obj_getter); } else if (method_name.StartsWith("set_") && prop_map.TryGetValue(method.Name.Substring(4), out prop)) // setter of property { LuaAPI.xlua_pushasciistring(L, prop.Name); translator.PushFixCSFunction(L, genPropSetter(type, prop, method.IsStatic)); LuaAPI.lua_rawset(L, method.IsStatic ? cls_setter : obj_setter); } else if (method_name == ".ctor" && method.IsConstructor) { continue; } else { if (overloads == null) { overloads = new List <MemberInfo>(); pending_methods.Add(method_key, overloads); } overloads.Add(method); } } foreach (var kv in pending_methods) { if (kv.Key.Name.StartsWith("op_")) // 操作符 { LuaAPI.xlua_pushasciistring(L, support_op[kv.Key.Name]); translator.PushFixCSFunction(L, new LuaCSFunction(translator.methodWrapsCache._GenMethodWrap(type, kv.Key.Name, kv.Value.ToArray()).Call)); LuaAPI.lua_rawset(L, obj_meta); } else { LuaAPI.xlua_pushasciistring(L, kv.Key.Name); translator.PushFixCSFunction(L, new LuaCSFunction(translator.methodWrapsCache._GenMethodWrap(type, kv.Key.Name, kv.Value.ToArray()).Call)); LuaAPI.lua_rawset(L, kv.Key.IsStatic ? cls_field : obj_field); } } IEnumerable <MethodInfo> extend_methods = GetExtensionMethodsOf(type); if (extend_methods != null) { foreach (var kv in (from extend_method in extend_methods select(MemberInfo) extend_method into member group member by member.Name)) { LuaAPI.xlua_pushasciistring(L, kv.Key); translator.PushFixCSFunction(L, new LuaCSFunction(translator.methodWrapsCache._GenMethodWrap(type, kv.Key, kv).Call)); LuaAPI.lua_rawset(L, obj_field); } } // init obj metatable LuaAPI.xlua_pushasciistring(L, "__gc"); LuaAPI.lua_pushstdcallcfunction(L, translator.metaFunctions.GcMeta); LuaAPI.lua_rawset(L, obj_meta); LuaAPI.xlua_pushasciistring(L, "__tostring"); LuaAPI.lua_pushstdcallcfunction(L, translator.metaFunctions.ToStringMeta); LuaAPI.lua_rawset(L, obj_meta); LuaAPI.xlua_pushasciistring(L, "__index"); LuaAPI.lua_pushvalue(L, obj_field); LuaAPI.lua_pushvalue(L, obj_getter); translator.PushFixCSFunction(L, item_getter); translator.PushAny(L, type.BaseType); LuaAPI.xlua_pushasciistring(L, Utils.LuaIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); LuaAPI.lua_pushnil(L); LuaAPI.gen_obj_indexer(L); //store in lua indexs function tables LuaAPI.xlua_pushasciistring(L, Utils.LuaIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); translator.Push(L, type); LuaAPI.lua_pushvalue(L, -3); LuaAPI.lua_rawset(L, -3); LuaAPI.lua_pop(L, 1); LuaAPI.lua_rawset(L, obj_meta); // set __index LuaAPI.xlua_pushasciistring(L, "__newindex"); LuaAPI.lua_pushvalue(L, obj_setter); translator.PushFixCSFunction(L, item_setter); translator.Push(L, type.BaseType); LuaAPI.xlua_pushasciistring(L, Utils.LuaNewIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); LuaAPI.lua_pushnil(L); LuaAPI.gen_obj_newindexer(L); //store in lua newindexs function tables LuaAPI.xlua_pushasciistring(L, Utils.LuaNewIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); translator.Push(L, type); LuaAPI.lua_pushvalue(L, -3); LuaAPI.lua_rawset(L, -3); LuaAPI.lua_pop(L, 1); LuaAPI.lua_rawset(L, obj_meta); // set __newindex //finish init obj metatable LuaAPI.xlua_pushasciistring(L, "UnderlyingSystemType"); translator.PushAny(L, type); LuaAPI.lua_rawset(L, cls_field); if (type != null && type.IsEnum) { LuaAPI.xlua_pushasciistring(L, "__CastFrom"); translator.PushFixCSFunction(L, genEnumCastFrom(type)); LuaAPI.lua_rawset(L, cls_field); } //set cls_field to namespace SetCSTable(L, type, cls_field); //finish set cls_field to namespace //init class meta LuaAPI.xlua_pushasciistring(L, "__index"); LuaAPI.lua_pushvalue(L, cls_getter); LuaAPI.lua_pushvalue(L, cls_field); translator.Push(L, type.BaseType); LuaAPI.xlua_pushasciistring(L, Utils.LuaClassIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); LuaAPI.gen_cls_indexer(L); //store in lua indexs function tables LuaAPI.xlua_pushasciistring(L, Utils.LuaClassIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); translator.Push(L, type); LuaAPI.lua_pushvalue(L, -3); LuaAPI.lua_rawset(L, -3); LuaAPI.lua_pop(L, 1); LuaAPI.lua_rawset(L, cls_meta); // set __index LuaAPI.xlua_pushasciistring(L, "__newindex"); LuaAPI.lua_pushvalue(L, cls_setter); translator.Push(L, type.BaseType); LuaAPI.xlua_pushasciistring(L, Utils.LuaClassNewIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); LuaAPI.gen_cls_newindexer(L); //store in lua newindexs function tables LuaAPI.xlua_pushasciistring(L, Utils.LuaClassNewIndexsFieldName); LuaAPI.lua_rawget(L, LuaIndexes.LUA_REGISTRYINDEX); translator.Push(L, type); LuaAPI.lua_pushvalue(L, -3); LuaAPI.lua_rawset(L, -3); LuaAPI.lua_pop(L, 1); LuaAPI.lua_rawset(L, cls_meta); // set __newindex LuaCSFunction constructor = translator.methodWrapsCache.GetConstructorWrap(type); if (constructor == null) { constructor = (RealStatePtr LL) => { return(LuaAPI.luaL_error(LL, "No constructor for " + type)); }; } LuaAPI.xlua_pushasciistring(L, "__call"); translator.PushFixCSFunction(L, constructor); LuaAPI.lua_rawset(L, cls_meta); LuaAPI.lua_pushvalue(L, cls_meta); LuaAPI.lua_setmetatable(L, cls_field); LuaAPI.lua_pop(L, 8); System.Diagnostics.Debug.Assert(top_enter == LuaAPI.lua_gettop(L)); }