码迷,mamicode.com
首页 > 其他好文 > 详细

Xlua 热补丁技术

时间:2020-08-16 00:00:37      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:ade   ring   object   href   manual   token   system   click   eth   

目录:?Xlua源码学习? 
一、xlua.hotfix对需要打补丁的类、方法进行替换。
xlua.hotfix = function(cs, field, func)
    if func == nil then func = false end
    local tbl = (type(field) == table) and field or {[field] = func}
    for k, v in pairs(tbl) do
        local cflag = ‘‘
        if k == .ctor then
            cflag = _c
            k = ctor
        end
        local f = type(v) == function and v or nil
        xlua.access(cs, cflag .. __Hotfix0_..k, f) -- at least one
        pcall(function()
            for i = 1, 99 do--重载
                xlua.access(cs, cflag .. __Hotfix..i.._..k, f)
            end
        end)
    end
    xlua.private_accessible(cs)
end
xlua.access:
public static int XLuaAccess(RealStatePtr L)
{
    try
    {
        ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L);
        Type type = getType(L, translator, 1);//静态方法,通过cls_table["UnderlyingSystemType"]获取ud。
        object obj = null;
        if (type == null && LuaAPI.lua_type(L, 1) == LuaTypes.LUA_TUSERDATA)
        {
            obj = translator.SafeGetCSObj(L, 1);//对象方法,获取对象object
            type = obj.GetType();
        }
 
        string fieldName = LuaAPI.lua_tostring(L, 2);
        BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
 
        if (LuaAPI.lua_gettop(L) > 2) // set
        {
            var field = type.GetField(fieldName, bindingFlags);
            if (field != null)
            {
                field.SetValue(obj, translator.GetObject(L, 3, field.FieldType));
                return 0;
            }
            var prop = type.GetProperty(fieldName, bindingFlags);
            if (prop != null)
            {
                prop.SetValue(obj, translator.GetObject(L, 3, prop.PropertyType), null);//lua_function转委托并进行赋值。
                return 0;
            }
        }
        else //get
        {
            var field = type.GetField(fieldName, bindingFlags);
            if (field != null)
            {
                translator.PushAny(L, field.GetValue(obj));
                return 1;
            }
            var prop = type.GetProperty(fieldName, bindingFlags);
            if (prop != null)
            {
                translator.PushAny(L, prop.GetValue(obj, null));
                return 1;
            }
        }
        return LuaAPI.luaL_error(L, "xlua.access, no field " + fieldName);
    }
}
以下面为例子:
xlua.hotfix(CS.Calc, add,function(a,b)
    print(Update in lua)
end)
1. xlua.access(CS.Calc, ‘__Hotfix0_add‘, func)。
2. 由于CS.Calc = cls_table,类型是LUA_TTABLE,通过cls_table["UnderlyingSystemType"]获取到类的ud。
3.通过ud获取到CS.Calc 的Type。translator.Get(L, -1, out value);
4.translator.GetObject把lua_function转成对应的委托。也就是上面截图的else的逻辑。由于xlua生成的补丁代码是带参数类型的委托,那么这边走的是把lua_function转成委托(__Gen_Delegate_ImpX)的分支。
5.委托赋值给CS.Calc. __Hotfix0_add。
二、xlua IL层面是如何把代码注入到源码的?
网上有个示例可以参考下:
[hotfix]
public class Calc
{
    int Add(int a, int b) 
    {
        return a + b;
    }
}
 
 
public class Calc
{
    static Func<object, int, int, int> __Hotfix0_Add = null; //xlua注入
    int Add(int a, int b) 
    {
        if (__Hotfix0_Add != null) return __Hotfix0_Add(this, a, b); //xlua注入
        return a + b;//原逻辑
    }
}
注入代码的逻辑在Hotfix.injectMethod里。

Xlua 热补丁技术

标签:ade   ring   object   href   manual   token   system   click   eth   

原文地址:https://www.cnblogs.com/wang-jin-fu/p/13508812.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有 京ICP备13008772号-2
迷上了代码!