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, );
.....
}
在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 原理的更多相关文章
- 深入理解xLua热更新原理
热更新简介 热更新是指在不需要重新编译打包游戏的情况下,在线更新游戏中的一些非核心代码和资源,比如活动运营和打补丁.热更新分为资源热更新和代码热更新两种,代码热更新实际上也是把代码当成资源的一种热更新 ...
- 深入xLua实现原理之Lua如何调用C#
xLua是腾讯的一个开源项目,为Unity. .Net. Mono等C#环境增加Lua脚本编程的能力.本文主要是探讨xLua下Lua调用C#的实现原理. Lua与C#数据通信机制 无论是Lua调用C# ...
- 深入xLua实现原理之C#如何调用Lua
本文主要是探讨xLua下C#调用Lua的实现原理,有关Lua如何调用C#的介绍可以查看深入xLua实现原理之Lua如何调用C# C#与Lua数据通信机制 无论是Lua调用C#,还是C#调用Lua,都需 ...
- 深入理解xLua基于IL代码注入的热更新原理
目前大部分手游都会采用热更新来解决应用商店审核周期长,无法满足快节奏迭代的问题.另外热更新能够有效降低版本升级所需的资源大小,节省玩家的时间和流量,这也使其成为移动游戏的主流更新方式之一. 热更新可以 ...
- Unity3D游戏xlua轻量级热修复框架
这是什么东西 前阵子刚刚集成xlua到项目,目的只有一个:对线上游戏C#逻辑有Bug的地方执行修复,通过考察了xlua和tolua,最终选择了xlua,原因如下: 1)项目已经到了后期,线上版本迭代了 ...
- lua热更框架之XLua
框架介绍 xLua是当下最流行的unity热更方案之一,作者是腾讯的车雄生前辈,自2016年初推出以来,已经在腾讯的多款游戏项目上应用,目前xLua已经开源到了GitHub.xLua最大的特色是不仅支 ...
- Unity下XLua方案的各值类型GC优化深度剖析
转自:http://gad.qq.com/article/detail/25645 前言 Unity下的C#GC Alloc(下面简称gc)是个大问题,而嵌入一个动态类型的Lua后,它们之间的交互很容 ...
- Unity3D游戏轻量级xlua热修复框架
Unity3D游戏轻量级xlua热修复框架 一 这是什么东西 前阵子刚刚集成xlua到项目,目的只有一个:对线上游戏C#逻辑有Bug的地方执行修复,通过考察xlua和tolua,最终选择了xlua ...
- ulua、tolua原理解析
在聊ulua.tolua之前,我们先来看看Unity热更新相关知识. 什么是热更新 举例来说: 游戏上线后,玩家下载第一个版本(70M左右或者更大),在运营的过程中,如果需要更换UI显示,或者修改游戏 ...
随机推荐
- idea 将部分class文件打包成jar使用
工作中有时候有太多模块堆放一块比较混乱,将某个功能(例如:三方支付)所需要的模块打包成jar使用起来会方便点. 步骤如下: 选择 Empty,然后为自己打的jar起个名字 然后在myjar上面右键 创 ...
- C++编程学习(十二) STL
一.简介 标准模板库STL,是一组模板类和函数.提供了: 1.容器.用于存储信息. 2.迭代器.用于访问容器中的信息. 3.算法.操作容器内容. 1.容器 STL有两种类型的容器类: (1)顺序容器 ...
- pyhton scipy最小二乘法(scipy.linalg.lstsq模块)
最小二乘法则是一种统计学习优化技术,它的目标是最小化误差平方之和来作为目标J(θ)J(θ),从而找到最优模型. 7. SciPy最小二乘法 最小二乘法则是一种统计学习优化技术,它的目标是最小化误差平方 ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-pencil
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- 08 SSM整合案例(企业权限管理系统):09.用户和角色操作
04.AdminLTE的基本介绍 05.SSM整合案例的基本介绍 06.产品操作 07.订单操作 08.权限控制 09.用户和角色操作 10.权限关联 11.AOP日志 09.用户和角色操作 1. 用 ...
- 动态弹出框,iframe的name包含一串随机数
由于name是随机的,要定位name比较困难,此处由于iframe的标签是唯一的,所以可以用tag_name定位 framename=driver.find_element_by_tag_name(& ...
- C++ 非白名单程序间接启动
主要的思路是不能用不受信任的程序直接参与创建进程,而是间接启动目标进程.比如你可以把目标程序创建快捷方式,然后设置快捷键.然后向桌面发快捷键的按键消息,目标程序就会被桌面程序启动.
- Result Maps collection already contains value for com.xxx.x.dao.xxxMapper.Bas
springboot启动时候,报错如下: Result Maps collection already contains value for com.xxx.xx.dao.xxxxxMapper.Ba ...
- cf 763A. Timofey and a tree
呵呵呵,直接判断是不是一个点连起来所有的特殊边(连接2不同颜色的点的边) (一开始还想各种各样奇怪的dfs...垃圾) #include<bits/stdc++.h> #define LL ...
- 015-PHP读取TXT记事本内容
<?php print("<H3>通过http协议打开文件</H3>\n"); // 通过 http 协议打开文件 if (!($myFile = f ...