xlua 原理

基于版本 104

可以直接在lua访问c#函数原理:

CS 是一个table,设置了一个__index函数,如果访问不存在的成员的时候,会走__index函数,调用import_type从C#中找到具体函数设置到CS中。以便下一次访问的时候直接使用

xlua在生产wrap时,会生成一个partial ObjectTranslator类,对该类添加了成员变量XLua_Gen_Initer_Register__ s_gen_reg_dumb_obj,在类的构造函数中会提交一个函数(AddIniter),执行该函数时会注册已经生成了wrap的wrap类和__Register方法到ObjectTranslator.delayWrap中。

没有生产类的wrap时,就不会有上面的过程,delayWrap就为空

在lua访问cs中不存在的类的时候,会触发ImportType,ImportType走方法TryDelayWrapLoader注册该类的wrap类和方法。

        public bool TryDelayWrapLoader(RealStatePtr L, Type type)
        {
.....
            if (delayWrap.TryGetValue(type, out loader))
            {
                delayWrap.Remove(type);
                loader(L);
            }
            else
            {
.....
                if (!DelegateBridge.Gen_Flag && !type.IsEnum() && !typeof(Delegate).IsAssignableFrom(type) && Utils.IsPublic(type))
                {
                    Type wrap = ce.EmitTypeWrap(type);
                    MethodInfo method = wrap.GetMethod("__Register", BindingFlags.Static | BindingFlags.Public);
                    method.Invoke(null, new object[] { L });
                }
                else
                {
                    Utils.ReflectionWrap(L, type, privateAccessibleFlags.Contains(type));
                }
.....

            return true;
        }

从方法中可以看到,如果delayWrap存在对于的wrap和Register函数,那么就走生成好的wrap代码;如果没有,非生成wrap模式就会走EmitTypeWrap方法,动态生成该类的wrap代码和Rigister函数。调用Register函数注册该wrap。如果采用生成wrap模式,DelegateBridge.Gen_Flag就会被生成的代码设置为true,那么凡是没有生成wrap的类代码,都会走Utils.ReflectionWrap

在ReflectionWrap中,对于方法会调用PushFixCSFunction把方法放入fix_cs_functions中,把把函数名,对应的索引和FixCSFunctionWraper注册到lua

        internal void PushFixCSFunction(RealStatePtr L, LuaCSFunction func)
        {
.....
                LuaAPI.xlua_pushinteger(L, fix_cs_functions.Count);
                fix_cs_functions.Add(func);
                LuaAPI.lua_pushstdcallcfunction(L, metaFunctions.FixCSFunctionWraper, 1);
.....
        }

在lua中调用该函数时,会走FixCSFunction,根据索引定位到具体的函数执行

        static int FixCSFunction(RealStatePtr L)
        {
            try
            {
                ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L);
                int idx = LuaAPI.xlua_tointeger(L, LuaAPI.xlua_upvalueindex(1));
                LuaCSFunction func = (LuaCSFunction)translator.GetFixCSFunction(idx);
                return func(L);
            }
            catch (Exception e)
            {
                return LuaAPI.luaL_error(L, "c# exception in FixCSFunction:" + e);
            }
        }

TODO hot fix 原理

  

猜你喜欢

转载自www.cnblogs.com/hygblog/p/9698982.html