基于版本 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, );
.....
}

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

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

Hotfix原理
以08_Hotfix中HotfixTest为列
修改HotfixTest的方法Update

xlua.hotfix(CS.HotfixTest, 'Update', function(self)
self.tick = self.tick +
if (self.tick % ) == then
print('<<<<<<<<Update in lua, tick = ' .. self.tick)
end
end

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 = , do
xlua.access(cs, cflag .. '__Hotfix'..i..'_'..k, f)
end
end)
end
xlua.private_accessible(cs)
end

经过xlua注入生成的Update代码如下

  private static DelegateBridge __Hotfix0_Update;
  private void Update()
{
DelegateBridge _Hotfix0_Update = __Hotfix0_Update;
if (_Hotfix0_Update != null)
{
_Hotfix0_Update.__Gen_Delegate_Imp18(this);
}
else if (++tick % == )
{
Debug.Log((object)(">>>>>>>>Update in C#, tick = " + tick));
}
}

xlua.access 对应方法 StaticLuaCallbacks.XLuaAccess

       public static int XLuaAccess(RealStatePtr L)
{
......
          Type type = getType(L, translator, );//HotfixTest
......
string fieldName = LuaAPI.lua_tostring(L, );// _Hotfix0_Update
...... if (LuaAPI.lua_gettop(L) > ) // set
{
var field = type.GetField(fieldName, bindingFlags);
if (field != null)
{
field.SetValue(obj, translator.GetObject(L, , field.FieldType));
return ;
}
var prop = type.GetProperty(fieldName, bindingFlags);
if (prop != null)
{
prop.SetValue(obj, translator.GetObject(L, , prop.PropertyType), null);
return ;
.......
}

在该方法中,设置方法对应的hotfix属性为lua函数。该例子中设置_Hotfix0_Update

  

xlua 原理的更多相关文章

  1. 深入理解xLua热更新原理

    热更新简介 热更新是指在不需要重新编译打包游戏的情况下,在线更新游戏中的一些非核心代码和资源,比如活动运营和打补丁.热更新分为资源热更新和代码热更新两种,代码热更新实际上也是把代码当成资源的一种热更新 ...

  2. 深入xLua实现原理之Lua如何调用C#

    xLua是腾讯的一个开源项目,为Unity. .Net. Mono等C#环境增加Lua脚本编程的能力.本文主要是探讨xLua下Lua调用C#的实现原理. Lua与C#数据通信机制 无论是Lua调用C# ...

  3. 深入xLua实现原理之C#如何调用Lua

    本文主要是探讨xLua下C#调用Lua的实现原理,有关Lua如何调用C#的介绍可以查看深入xLua实现原理之Lua如何调用C# C#与Lua数据通信机制 无论是Lua调用C#,还是C#调用Lua,都需 ...

  4. 深入理解xLua基于IL代码注入的热更新原理

    目前大部分手游都会采用热更新来解决应用商店审核周期长,无法满足快节奏迭代的问题.另外热更新能够有效降低版本升级所需的资源大小,节省玩家的时间和流量,这也使其成为移动游戏的主流更新方式之一. 热更新可以 ...

  5. Unity3D游戏xlua轻量级热修复框架

    这是什么东西 前阵子刚刚集成xlua到项目,目的只有一个:对线上游戏C#逻辑有Bug的地方执行修复,通过考察了xlua和tolua,最终选择了xlua,原因如下: 1)项目已经到了后期,线上版本迭代了 ...

  6. lua热更框架之XLua

    框架介绍 xLua是当下最流行的unity热更方案之一,作者是腾讯的车雄生前辈,自2016年初推出以来,已经在腾讯的多款游戏项目上应用,目前xLua已经开源到了GitHub.xLua最大的特色是不仅支 ...

  7. Unity下XLua方案的各值类型GC优化深度剖析

    转自:http://gad.qq.com/article/detail/25645 前言 Unity下的C#GC Alloc(下面简称gc)是个大问题,而嵌入一个动态类型的Lua后,它们之间的交互很容 ...

  8. Unity3D游戏轻量级xlua热修复框架

    Unity3D游戏轻量级xlua热修复框架   一 这是什么东西 前阵子刚刚集成xlua到项目,目的只有一个:对线上游戏C#逻辑有Bug的地方执行修复,通过考察xlua和tolua,最终选择了xlua ...

  9. ulua、tolua原理解析

    在聊ulua.tolua之前,我们先来看看Unity热更新相关知识. 什么是热更新 举例来说: 游戏上线后,玩家下载第一个版本(70M左右或者更大),在运营的过程中,如果需要更换UI显示,或者修改游戏 ...

随机推荐

  1. VUE - 使用axios数据请求时数据绑定时 报错 TypeError: Cannot set property 'xxxx' of undefined 的解决办法

     created() {     var that=this     axios.get('http://jsonplaceholder.typicode.com/todos')     .then( ...

  2. android中的简单animation(一)shake

    1.shake animation_1.xml: <?xml version="1.0" encoding="utf-8"?> <Linear ...

  3. imp.load_source的用法

    imp.load_source(name,pathname[,file])的作用把源文件pathname导入到name模块中,name可以是自定义的名字或者内置的模块名称. 假设在路径E:/Code/ ...

  4. python多进程编程中常常能用到的几种方法

    python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU资源,在python中大部分情况需要使用多进程.python提供了非常好用的多进程包Multiprocessing,只需要定义 ...

  5. 047、Java中使用if…else if…else判断

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

  6. 7.7 Varnishadm命令

  7. 【LOJ3043】「ZJOI2019」线段树

    题面 问题可以转化为每次区间覆盖操作有 \(\frac{1}{2}\) 的概率进行,求标记和的期望.于是我们只要求出所有点有标记的概率即可. 我们设 \(f_i\) 表示节点 \(i\) 有标记的概率 ...

  8. sql语句中 and 与or 的优先级

  9. CSS - 强制换行和禁止换行强制换行 和禁止换行样

    强制换行 word-break: break-all;       只对英文起作用,以字母作为换行依据. word-wrap: break-word;   只对英文起作用,以单词作为换行依据. whi ...

  10. 十四、JavaScript之不同类型变量相加

    一.代码如下 二.效果如下 <!DOCTYPE html> <html> <meta http-equiv="Content-Type" conten ...