更新Xlua 到最新版本

This commit is contained in:
2024-09-04 02:07:48 +08:00
parent dba48de5cf
commit 5b79a2d4bb
227 changed files with 5594 additions and 878 deletions
Assets
Plugins
XLua.meta
XLua
CHANGELOG.txtCHANGELOG.txt.meta
Doc
Editor.meta
Editor
Gen.meta
Gen
DelegatesGensBridge.csDelegatesGensBridge.cs.metaEnumWrap.csEnumWrap.cs.metaIMarketingActRetDelBridge.cs.metaLuaMainWrap.cs.metaLuaUIBehaviourWrap.cs.metaPackUnpack.cs.metaSdkControlWrap.csSdkControlWrap.cs.metaSystem_Collections_Generic_List_1_System_Int32_Wrap.cs.metaSystem_Collections_HashtableWrap.cs.metaSystem_Collections_IEnumerableBridge.cs.metaSystem_Collections_IEnumeratorBridge.cs.metaSystem_ObjectWrap.cs.metaTableManagerLuaWrap.cs.metaTutorial_BaseClassWrap.csTutorial_BaseClassWrap.cs.metaTutorial_CSCallLua_ItfDBridge.csTutorial_CSCallLua_ItfDBridge.cs.metaTutorial_DerivedClassExtensionsWrap.csTutorial_DerivedClassExtensionsWrap.cs.metaTutorial_DerivedClassWrap.csTutorial_DerivedClassWrap.cs.metaTutorial_ICalcWrap.csTutorial_ICalcWrap.cs.metaUnityEngine_AnimationClipWrap.cs.metaUnityEngine_AnimationCurveWrap.cs.metaUnityEngine_BehaviourWrap.cs.metaUnityEngine_BoundsWrap.cs.metaUnityEngine_ColorWrap.cs.metaUnityEngine_ComponentWrap.cs.metaUnityEngine_DebugWrap.cs.metaUnityEngine_GameObjectWrap.cs.metaUnityEngine_KeyframeWrap.cs.metaUnityEngine_LightWrap.cs.metaUnityEngine_MathfWrap.cs.metaUnityEngine_MonoBehaviourWrap.cs.metaUnityEngine_ObjectWrap.cs.metaUnityEngine_ParticleSystemWrap.cs.metaUnityEngine_QuaternionWrap.cs.metaUnityEngine_Ray2DWrap.cs.metaUnityEngine_RayWrap.cs.metaUnityEngine_RendererWrap.cs.metaUnityEngine_ResourcesWrap.cs.metaUnityEngine_SkinnedMeshRendererWrap.cs.metaUnityEngine_TextAssetWrap.cs.metaUnityEngine_TimeWrap.cs.metaUnityEngine_TransformWrap.cs.metaUnityEngine_Vector2Wrap.cs.metaUnityEngine_Vector3Wrap.cs.metaUnityEngine_Vector4Wrap.cs.metaUnityEngine_WWWWrap.cs.metaWrapPusher.csWrapPusher.cs.metaXLuaGenAutoRegister.csXLuaGenAutoRegister.cs.metalink.xmllink.xml.meta
Resources
Src.meta
Src
CodeEmit.csCodeEmit.cs.metaCopyByValue.csCopyByValue.cs.metaDelegateBridge.csDelegateBridge.cs.metaEditor.meta
Editor
GenAttributes.csGenAttributes.cs.metaGenericDelegateBridge.csGenericDelegateBridge.cs.metaInternalGlobals.csInternalGlobals.cs.metaLuaBase.csLuaBase.cs.metaLuaDLL.csLuaDLL.cs.metaLuaEnv.csLuaEnv.cs.metaLuaException.csLuaException.cs.metaLuaFunction.csLuaFunction.cs.metaLuaTable.csLuaTable.cs.metaMethodWarpsCache.csMethodWarpsCache.cs.metaObjectCasters.csObjectCasters.cs.metaObjectPool.csObjectPool.cs.metaObjectTranslator.csObjectTranslator.cs.metaObjectTranslatorPool.csObjectTranslatorPool.cs.metaRawObject.csRawObject.cs.metaSignatureLoader.csSignatureLoader.cs.metaStaticLuaCallbacks.csStaticLuaCallbacks.cs.metaTemplateEngine.meta
TemplateEngine
TypeExtensions.csTypeExtensions.cs.metaUtils.csUtils.cs.meta
Tutorial.meta
Tutorial

@ -117,7 +117,9 @@ For example, the following adds a property of GameObject and a method of FileInf
[BlackList]
public static List<List<string>> BlackList = new List<List<string>>() {
new List<string>(){"UnityEngine.GameObject", "networkView"},
//new List<string>(){ typeof(UnityEngine.GameObject).FullName, "networkView"},
new List<string>(){"System.IO.FileInfo", "GetAccessControl", "System.Security.AccessControl.AccessControlSections"},
//new List<string>(){ typeof(System.IO.FileInfo).FullName, "GetAccessControl",typeof(System.Security.AccessControl.AccessControlSections).FullName },
};
~~~

@ -48,9 +48,7 @@ util.hotfix_ex(class, method_name, fix)
Like other configurations, there are two methods:
1. Add Hotfix flag directly in the type;
2. Configure a list in the static field or property of a static type. Properties can be used to implement more complex configurations, such as whitelisting based on Namespace.
Configure a list in the static field or property of a static type. Properties can be used to implement more complex configurations, such as whitelisting based on Namespace.
~~~csharp
public static class HotfixCfg

@ -7,7 +7,7 @@ Material:
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: logo
m_Shader: {fileID: 4800000, guid: 8c3ff126303ac344587210cb9f08ff6c, type: 3}
m_Shader: {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0

@ -1,6 +1,9 @@
## C# API
### LuaEnv类
#### object[] DoString(string chunk, string chunkName = "chuck", LuaTable env = null)
描述:
执行一个代码块。
@ -14,7 +17,7 @@
代码块里return语句的返回值;
比如return 1, “hello”DoString返回将包含两个object的数组 一个是double类型的1 一个是string类型的“hello”
例如:
LuaEnv luaenv = new LuaEnv();
@ -38,7 +41,7 @@
代表该代码块的delegate或者LuaFunction类
#### LuaTable Global;
#### LuaTable Global
描述:
@ -64,45 +67,44 @@
#### void Dispose()
描述:
Dispose该LuaEnv。
> LuaEnv的使用建议全局就一个实例并在Update中调用GC方法完全不需要时调用Dispose
### LuaTable类
#### T Get<T>(string key)
#### `T Get<T>(string key)`
描述:
获取在key下类型为T的value如果不存在或者类型不匹配返回null
#### T GetInPath<T>(string path)
#### `T GetInPath<T>(string path)`
描述:
和Get的区别是这个函数会识别path里头的“.”比如var i = tbl.GetInPath<int>(“a.b.c”)相当于在lua里头执行i = tbl.a.b.c避免仅为了获取中间变量而多次调用Get执行效率更高。
#### void SetInPath<T>(string path, T val)
#### `void SetInPath<T>(string path, T val)`
描述:
和GetInPaht<T>对应的setter
#### void Get<TKey, TValue>(TKey key, out TValue value)
#### `void Get<TKey, TValue>(TKey key, out TValue value)`
描述:
上面的API的Key都只能是string而这个API无此限制
#### void Set<TKey, TValue>(TKey key, TValue value)
#### `void Set<TKey, TValue>(TKey key, TValue value)`
描述:
对应Get<TKey, TValue>的setter
#### T Cast<T>()
#### `T Cast<T>()`
描述:
@ -111,12 +113,12 @@
#### void SetMetaTable(LuaTable metaTable)
描述:
设置metaTable为table的metatable
### LuaFunction类
### LuaFunction
> 注意用该类访问Lua函数会有boxingunboxing的开销为了性能考虑需要频繁调用的地方不要用该类。建议通过table.Get<ABCDelegate>获取一个delegate再调用假设ABCDelegateC#的一个delegate。在使用使用table.Get<ABCDelegate>之前请先把ABCDelegate加到代码生成列表。
> 注意用该类访问Lua函数会有boxingunboxing的开销为了性能考虑需要频繁调用的地方不要用该类。建议通过 `table.Get<ABCDelegate>` 获取一个 delegate 再调用(假设 `ABCDelegate` 是 C# 的一个 delegate。在使用使用 `table.Get<ABCDelegate>` 之前请先把ABCDelegate加到代码生成列表。
#### object[] Call(params object[] args)
@ -155,29 +157,27 @@
描述:
访问一个C#静态成员
例如:
Print(CS.UnityEngine.Vector3.one)
#### CS.namespace.enum.field
描述:
访问一个枚举值
#### typeof函数
描述:
类似C#里头的typeof关键字返回一个Type对象比如GameObject.AddComponent其中一个重载需要一个Type参数
例如:
newGameObj:AddComponent(typeof(CS.UnityEngine.ParticleSystem))
#### 无符号64位支持
##### uint64.tostring
@ -201,9 +201,9 @@
##### uint64.remainder
描述:
无符号数取模。
##### uint64.parse
描述:
@ -212,24 +212,26 @@
#### xlua.structclone
描述:
克隆一个c#结构体
#### xlua.private_accessible(class)
#### xlua.private_accessible(class)
描述:
让一个类的私有字段,属性,方法等可用
例子:
xlua.private_accessible(CS.UnityEngine.GameObject)
xlua.private_accessible(CS.UnityEngine.GameObject)
#### xlua.get_generic_method
描述:
获取一个泛型方法
例子:
~~~lua
```lua
local foo_generic = xlua.get_generic_method(CS.GetGenericMethodTest, 'Foo')
local bar_generic = xlua.get_generic_method(CS.GetGenericMethodTest, 'Bar')
@ -243,16 +245,16 @@ print(ret)
-- call static method
bar(2, nil)
~~~
```
#### cast函数
描述:
指明以特定的接口访问对象这在实现类无法访问的时候比如internal修饰很有用这时可以这么来假设下面的calc对象实现了C#的PerformentTest.ICalc接口
例子:
cast(calc, typeof(CS.PerformentTest.ICalc))
然后就木有其它API了
@ -272,7 +274,6 @@ bar(2, nil)
### 基本数据类型
|C#类型|Lua类型|
|-|-|
|sbytebyteshortushortintuintdoublecharfloat|number|
@ -291,24 +292,24 @@ bar(2, nil)
|class或者 struct的实例|userdatatable|
|methoddelegate|function|
#### LuaTable
#### LuaTable
C#侧指明从Lua侧输入包括C#方法的输入参数或者Lua方法的返回值LuaTable类型则要求Lua侧为table。或者Lua侧的table在C#侧未指明类型的情况下转换成LuaTable
#### LuaFunction
#### LuaFunction
C#侧指明从Lua侧输入包括C#方法的输入参数或者Lua方法的返回值LuaFunction类型则要求Lua侧为function。或者Lua侧的function在C#侧未指明类型的情况下转换成LuaFunction
#### LuaUserData
#### LuaUserData
对应非C# Managered对象的lua userdata。
对应非 C# Managered 对象的lua userdata。
#### class或者 struct的实例:
#### class 或者 struct 的实例
从C#传一个class或者struct的实例将映射到Lua的userdata并通过__index访问该userdata的成员
C#侧指明从Lua侧输入指定类型对象Lua侧为该类型实例的userdata可以直接使用如果该指明类型有默认构造函数Lua侧是table则会自动转换转换规则是调用构造函数构造实例并用table对应字段转换到c#对应值后赋值各成员
#### method delegate
#### method delegate
成员方法以及delegate都是对应lua侧的函数。
C#侧的普通参数以及引用参数对应lua侧函数参数C#侧的返回值对应于Lua的第一个返回值引用参数和out参数则按序对应于Lua的第2到第N个参数。

@ -46,7 +46,7 @@
1. 获取一个全局基本数据类型
访问LuaEnv.Global就可以了上面有个模版Get方法可指定返回的类型。
luaenv.Global.Get<int>("a")
luaenv.Global.Get<string>("b")
luaenv.Global.Get<bool>("c")
@ -66,7 +66,7 @@
那有没有引用方式的映射呢?有,下面这个就是:
2. 映射到一个interface
这种方式依赖于生成代码如果没生成代码会抛InvalidCastException异常代码生成器会生成这个interface的实例如果get一个属性生成代码会get对应的table字段如果set属性也会设置对应的字段。甚至可以通过interface的方法访问lua的函数。
3. 更轻量级的by value方式映射到Dictionary<>List<>
@ -74,7 +74,7 @@
不想定义class或者interface的话可以考虑用这个前提table下key和value的类型都是一致的。
4. 另外一种by ref方式映射到LuaTable类
这种方式好处是不需要生成代码但也有一些问题比如慢比方式2要慢一个数量级比如没有类型检查。
3. 访问一个全局的function
@ -93,7 +93,7 @@
delegate的使用就更简单了直接像个函数那样用就可以了。
2. 映射到LuaFunction
这种方式的优缺点刚好和第一种相反。
使用也简单LuaFunction上有个变参的Call函数可以传任意类型任意个数的参数返回值是object的数组对应于lua的多返回值。
@ -101,9 +101,9 @@
1. 访问lua全局数据特别是table以及function代价比较大建议尽量少做比如在初始化时把要调用的lua function获取一次映射到delegate保存下来后续直接调用该delegate即可。table也类似。
2. 如果lua的实现的部分都以delegate和interface的方式提供使用方可以完全和xLua解耦由一个专门的模块负责xlua的初始化以及delegate、interface的映射然后把这些delegate和interface设置到要用到它们的地方。
2. 如果lua的实现的部分都以delegate和interface的方式提供使用方可以完全和xLua解耦由一个专门的模块负责xlua的初始化以及delegate、interface的映射然后把这些delegate和interface设置到要用到它们的地方。
### Lua调用C#
### Lua 调用 C#
> 本章节涉及到的实例均在XLua\Tutorial\LuaCallCSharp下
@ -167,11 +167,12 @@ xlua支持通过派生类访问基类的静态属性静态方法
##### 参数的输入输出属性outref
Lua调用的参数处理规则C#的普通参数算一个输入形参ref修饰的算一个输入形参out不算然后从左往右对应lua 调用的实参列表;
Lua调用的参数处理规则C#的普通参数算一个输入形参ref修饰的算一个输入形参out不算然后从左往右对应lua 调用的实参列表;
Lua调用的返回值处理规则C#函数的返回值如果有的话算一个返回值out算一个返回值ref算一个返回值然后从左往右对应lua的多返回值。
Lua调用的返回值处理规则C#函数的返回值如果有的话算一个返回值out算一个返回值ref算一个返回值然后从左往右对应lua的多返回值。
##### 重载方法
直接通过不同的参数类型进行重载函数的访问,例如:
testobj:TestFunc(100)
@ -190,6 +191,7 @@ Lua调用测的返回值处理规则C#函数的返回值(如果有的话)
和C#调用有默认值参数的函数一样,如果所给的实参少于形参,则会用默认值补上。
##### 可变参数方法
对于C#的如下方法
void VariableParamsFunc(int a, params string[] strs)

@ -1,22 +1,22 @@
# 通用字节码
不少项目希望把项目的lua源码通过luac编译后加载但官方lua有个缺陷字节码是分32位和64位版本的换句话你32lua环境只能跑32luac编译出来的东西。
不少项目希望把项目的 lua 源码通过 luac 编译后加载,但官方 lua 有个缺陷:字节码是分 32 位和 64 位版本的,换句话你 32lua 环境只能跑 32luac 编译出来的东西。
为此xLua尝试对lua源码做了少许改造可以编译一份字节码跨平台使用。
为此xLua 尝试对 lua 源码做了少许改造,可以编译一份字节码,跨平台使用。
## 注意事项
* 1、如果你做了本文所描述的改动你的xLua将加载不了官方luac所编译的字节码
* 1、如果你做了本文所描述的改动你的 xLua 将加载不了官方 luac 所编译的字节码;
* 2、截至2018/9/14已知此改法在一个上线一个多月的项目正常运行但不代表此改法在任何情况都没问题。
* 2、截至 2018/9/14已知此改法在一个上线一个多月的项目正常运行但不代表此改法在任何情况都没问题。
## 操作指南
### 1、编译xluaPlugins
### 1、编译 xluaPlugins
修改各平台编译脚本在cmake命令加上-DLUAC_COMPATIBLE_FORMAT=ON参数以make_win64_lua53.bat为例修改后是这样的
修改各平台编译脚本,在 cmake 命令加上 `-DLUAC_COMPATIBLE_FORMAT=ON` 参数,以 make_win64_lua53.bat 为例,修改后是这样的:
~~~bash
```bash
mkdir build64 & pushd build64
cmake -DLUAC_COMPATIBLE_FORMAT=ON -G "Visual Studio 14 2015 Win64" ..
popd
@ -24,18 +24,18 @@ cmake --build build64 --config Release
md plugin_lua53\Plugins\x86_64
copy /Y build64\Release\xlua.dll plugin_lua53\Plugins\x86_64\xlua.dll
pause
~~~
```
用修改后的编译脚本重新编译各平台的xlua库并覆盖原Plugins目录下对应文件。
用修改后的编译脚本重新编译各平台的 xlua 库,并覆盖原 Plugins 目录下对应文件。
## 2、编译能生成兼容格式的luac后续只能用这特定的luac和步骤1的Plugins配套使用
到[这里](../../../build/luac/),如果你想编译window版本的执行make_win64.bat如果你要编译mac或者linux的用make_unix.sh
到[这里](../../../build/luac/),如果你想编译 Windows 版本的,执行 make_win64.bat如果你要编译 Mac 或者 Linux 用make_unix.sh
## 3、加载字节码
通过CustomLoader加载即可CustomLoader的详细情况请看教程。这个步骤常犯的错误是用某种Encoding去加载二进制文件这会破坏lua字节码文件格式。谨记得以二进制方式加载。
通过 CustomLoader 加载即可CustomLoader 的详细情况请看教程。这个步骤常犯的错误是用某种Encoding去加载二进制文件这会破坏lua字节码文件格式。谨记得以二进制方式加载。
## PS: OpCode修改
有项目想修改为专用格式的字节码直接在lua源码目前是lua-5.3.5上修改后重新执行上述1、2操作步骤即可。
有项目想修改为专用格式的字节码,直接在 lua 源码目前是lua-5.3.5上修改后重新执行上述1、2操作步骤即可。

@ -13,7 +13,7 @@ xLua所有的配置都支持三种方式打标签静态列表动态列
xLua用白名单来指明生成哪些代码而白名单通过attribute来配置比如你想从lua调用c#的某个类希望生成适配代码你可以为这个类型打一个LuaCallCSharp标签
~~~csharp
```csharp
[LuaCallCSharp]
publicclassA
@ -21,7 +21,7 @@ publicclassA
}
~~~
```
该方式方便但在il2cpp下会增加不少的代码量不建议使用。
@ -29,7 +29,7 @@ publicclassA
有时我们无法直接给一个类型打标签比如系统api没源码的库或者实例化的泛化类型这时你可以在一个静态类里声明一个静态字段该字段的类型除BlackList和AdditionalProperties之外只要实现了IEnumerable&lt;Type&gt;就可以了(这两个例外后面具体会说),然后为这字段加上标签:
~~~csharp
```csharp
[LuaCallCSharp]
public static List<Type> mymodule_lua_call_cs_list = new List<Type>()
@ -38,7 +38,7 @@ public static List<Type> mymodule_lua_call_cs_list = new List<Type>()
typeof(Dictionary<string, int>),
};
~~~
```
这个字段需要放到一个 **静态类** 里头,建议放到 **Editor目录**
@ -46,7 +46,7 @@ public static List<Type> mymodule_lua_call_cs_list = new List<Type>()
声明一个静态属性,打上相应的标签即可。
~~~csharp
```csharp
[Hotfix]
public static List<Type> by_property
@ -59,7 +59,7 @@ public static List<Type> by_property
}
}
~~~
```
Getter是代码你可以实现很多效果比如按名字空间配置按程序集配置等等。
@ -79,7 +79,7 @@ xLua只会生成加了该配置的类型不会自动生成其父类的适配
一个C#类型类型加了这个配置xLua会生成link.xml阻止il2cpp的代码剪裁。
对于扩展方法必须加上LuaCallCSharp或者ReflectionUse才可以被访问到。
对于扩展方法,必须加上 `LuaCallCSharp` 或者 `ReflectionUse` 才可以被访问到。
建议所有要在Lua访问的类型要么加LuaCallCSharp要么加上ReflectionUse这才能够保证在各平台都能正常运行。
@ -87,7 +87,7 @@ xLua只会生成加了该配置的类型不会自动生成其父类的适配
指明一个类里头的部分函数、字段、属性不生成代码,通过反射访问。
只能标准Dictionary<Type, List<string>>的field或者property。key指明的是生效的类value是一个列表配置的是不生成代码的函数、字段、属性的名字。
只能标准 `Dictionary<Type, List<string>>` 的field或者property。key指明的是生效的类value是一个列表配置的是不生成代码的函数、字段、属性的名字。
和ReflectionUse的区别是1、ReflectionUse指明的是整个类2、当第一次访问一个函数字段、属性ReflectionUse会把整个类都wrap而DoNotGen只wrap该函数字段、属性换句话DoNotGen更lazy一些
@ -99,7 +99,7 @@ xLua只会生成加了该配置的类型不会自动生成其父类的适配
### XLua.GCOptimize
一个C#纯值类型指的是一个只包含值类型的struct可以嵌套其它只包含值类型的struct或者C#枚举值加上了这个配置。xLua会为该类型生成gc优化代码效果是该值类型在lua和c#间传递不产生C#gc alloc该类型的数组访问也不产生gc。各种无GC的场景可以参考05\_NoGc例子。
一个C#纯值类型指的是一个只包含值类型的struct可以嵌套其它只包含值类型的struct或者C#枚举值加上了这个配置。xLua会为该类型生成gc优化代码效果是该值类型在lua和c#间传递不产生C#gc alloc该类型的数组访问也不产生gc。各种无GC的场景可以参考 `05_Gc` 例子。
除枚举之外包含无参构造函数的复杂类型都会生成lua table到该类型以及改类型的一维数组的转换代码这将会优化这个转换的性能包括更少的gc alloc。
@ -107,7 +107,7 @@ xLua只会生成加了该配置的类型不会自动生成其父类的适配
这个是GCOptimize的扩展配置有的时候一些struct喜欢把field做成是私有的通过property来访问field这时就需要用到该配置默认情况下GCOptimize只对public的field打解包
标签方式比较简单配置方式复杂一点要求是Dictionary&lt;Type, List&lt;string&gt;&gt;类型DictionaryKey是要生效的类型Value是属性名列表。可以参考XLua对几个UnityEngine下值类型的配置SysGCOptimize类。
标签方式比较简单,配置方式复杂一点,要求是 `Dictionary<Type, List<string>>` 类型DictionaryKey 是要生效的类型Value 是属性名列表。可以参考XLua对几个UnityEngine下值类型的配置SysGCOptimize类。
### XLua.BlackList
@ -115,19 +115,21 @@ xLua只会生成加了该配置的类型不会自动生成其父类的适配
标签方式比较简单,对应的成员上加就可以了。
由于考虑到有可能需要把重载函数的其中一个重载列入黑名单配置方式比较复杂类型是List&lt;List&lt;string&gt;&gt;对于每个成员在第一层List有一个条目第二层List是个string的列表第一个string是类型的全路径名第二个string是成员名如果成员是一个方法还需要从第三个string开始把其参数的类型全路径全列出来。
由于考虑到有可能需要把重载函数的其中一个重载列入黑名单,配置方式比较复杂,类型是 `List<List<string>>`对于每个成员在第一层List有一个条目第二层List是个string的列表第一个string是类型的全路径名第二个string是成员名如果成员是一个方法还需要从第三个string开始把其参数的类型全路径全列出来。
例如下面是对GameObject的一个属性以及FileInfo的一个方法列入黑名单
例如下面是对 GameObject 的一个属性以及FileInfo的一个方法列入黑名单
~~~csharp
```csharp
[BlackList]
public static List<List<string>> BlackList = new List<List<string>>() {
new List<string>(){"UnityEngine.GameObject", "networkView"},
//new List<string>(){ typeof(UnityEngine.GameObject).FullName, "networkView"},
new List<string>(){"System.IO.FileInfo", "GetAccessControl", "System.Security.AccessControl.AccessControlSections"},
//new List<string>(){ typeof(System.IO.FileInfo).FullName, "GetAccessControl",typeof(System.Security.AccessControl.AccessControlSections).FullName },
};
~~~
```
### 下面是生成期配置必须放到Editor目录下

@ -16,7 +16,7 @@ xLua的生成引擎支持二次开发你可以利用它来生成一些文本
示例:
~~~xml
```xml
<%
require "TemplateCommon"
%>
@ -30,47 +30,47 @@ require "TemplateCommon"
</assembly>
<%end)%>
</linker>
~~~
```
TemplateCommon有一些预定义的函数可以使用比如ForEachCsList可以搜索下工程的TemplateCommon.lua.txt看下有那些函数可以用就普通的lua而已你自己写一套也可以。
## API
~~~csharp
```csharp
public static void CSObjectWrapEditor.Generator.CustomGen(string template_src, GetTasks get_tasks)
~~~
```
* template_src 模版的源码;
* get_tasks 回调函数类型是GetTasks用来接受用户的配置返回需要注入到模版的数据以及文件的输出流
~~~csharp
```csharp
public delegate IEnumerable<CustomGenTask> GetTasks(LuaEnv lua_env, UserConfig user_cfg);
~~~
```
* lua_env LuaEnv对象因为返回的模版数据需要放到LuaTable需要用到LuaEnv.NewTable
* user_cfg 用户的配置;
* return 返回值中CustomGenTask代表的是一个生成文件而IEnumerable类型表示同一个模版可以生成多个文件
~~~csharp
```csharp
public struct UserConfig
{
public IEnumerable<Type> LuaCallCSharp;
public IEnumerable<Type> CSharpCallLua;
public IEnumerable<Type> ReflectionUse;
}
~~~
```
~~~csharp
```csharp
public struct CustomGenTask
{
public LuaTable Data;
public TextWriter Output;
}
~~~
```
示例:
~~~csharp
```csharp
public static IEnumerable<CustomGenTask> GetTasks(LuaEnv lua_env, UserConfig user_cfg)
{
LuaTable data = lua_env.NewTable();
@ -86,7 +86,7 @@ public static IEnumerable<CustomGenTask> GetTasks(LuaEnv lua_env, UserConfig use
false, Encoding.UTF8)
};
}
~~~
```
* 这里只生成一个文件故只返回一个CustomGenTask
* data就是模版要使用的数据这里塞了一个assembly_infos字段这个字段如何使用可以回头看看模版部分
@ -97,13 +97,13 @@ public static IEnumerable<CustomGenTask> GetTasks(LuaEnv lua_env, UserConfig use
示例:
~~~csharp
```csharp
[GenCodeMenu]//加到Generate Code菜单里头
public static void GenLinkXml()
{
Generator.CustomGen(ScriptableObject.CreateInstance<LinkXmlGen>().Template.text, GetTasks);
}
~~~
```
ps以上所有相关代码都在XLua\Src\Editor\LinkXmlGen目录下也正是文章开头说的link.xml的生成功能的实现。

@ -68,7 +68,13 @@ ios和osx需要在mac下编译。
## 报类似“xlua.access, no field __Hitfix0_Update”的错误怎么解决
按[Hotfix操作指南](hotfix.md)一步步操作。
按[Hotfix操作指南](hotfix.md)一步步操作,以及注意事项。确保上述步骤完成后,可尝试使用[解决方案](https://github.com/Tencent/xLua/issues/850)
出现这报错,肯定是这个导致的:最终包的这个方法(函数)没注入。
但造成“最终包的这个方法函数没注入”的原因会有很多比如没按文档操作注入失败比如Hotfix列表漏了这个类比如你的打包脚本在注入后又触发了重新编译覆盖了注入结果。。。
统一的解决方式是找出并解决导致“最终包的这个方法(函数)没注入”的具体原因。
## visual studio 2017下编译UWP原生库
@ -90,6 +96,8 @@ visual studio 2017需要安装1、“工作负载”下的“通用Window平
如果编辑器下没问题发布到手机报这错表示你发布前没生成代码执行“XLua/Generate Code”
如果你Unity版本大于或等于2018看下前面兼容性的章节。
## unity5.5以上执行"XLua/Hotfix Inject In Editor"菜单会提示"WARNING: The runtime version supported by this application is unavailable."
这是因为注入工具是用.net3.5编译而unity5.5意思MonoBleedingEdge的mono环境并没3.5支持导致的不过一般而言都向下兼容目前为止也没发现该warning带来什么问题。
@ -192,6 +200,7 @@ end)
```
3、如果xlua版本大于2.1.12的话新增反射调用泛型方法的支持有一定的限制看后面的说明比如对于这么个C#类型
```csharp
public class GetGenericMethodTest
{
@ -214,7 +223,9 @@ public class GetGenericMethodTest
}
}
```
在lua那这么调用
```lua
local foo_generic = xlua.get_generic_method(CS.GetGenericMethodTest, 'Foo')
local bar_generic = xlua.get_generic_method(CS.GetGenericMethodTest, 'Bar')
@ -252,12 +263,12 @@ bar(2, nil)
如果你的版本大于2.1.11可以用get_Item来获取值用set_Item来设置值。要注意只有this[string field]或者this[object field]才有这两个替代api其它类型的key是没有的。
~~~lua
```lua
dic:set_Item('a', 1)
dic:set_Item('b', 2)
print(dic:get_Item('a'))
print(dic:get_Item('b'))
~~~
```
如果你的版本小于或等于2.1.11建议直接方法该操作符的等效方法比如Dictionary的TryGetValue如果该方法没有提供可以在C#那通过Extension method封装一个使用。
@ -267,7 +278,7 @@ print(dic:get_Item('b'))
对应这种情况可以为UnityEngine.Object写一个扩展方法
~~~csharp
```csharp
[LuaCallCSharp]
[ReflectionUse]
public static class UnityEngineObjectExtention
@ -277,35 +288,35 @@ public static class UnityEngineObjectExtention
return o == null;
}
}
~~~
```
然后在lua那你对所有UnityEngine.Object实例都使用IsNull判断
~~~lua
```lua
print(go:GetComponent('Animator'):IsNull())
~~~
```
## 泛型实例怎么构造
涉及的类型都在mscorlibAssembly-CSharp程序集的话泛型实例的构造和普通类型是一样的都是CS.namespace.typename()可能比较特殊的是typename的表达泛型实例的typename的表达包含了标识符非法符号最后一部分要换成["typename"]以List<string>为例
~~~lua
```lua
local lst = CS.System.Collections.Generic["List`1[System.String]"]()
~~~
```
如果某个泛型实例的typename不确定可以在C#测打印下typeof(不确定的类型).ToString()
如果涉及mscorlibAssembly-CSharp程序集之外的类型的话可以用C#的反射来做
~~~lua
```lua
local dic = CS.System.Activator.CreateInstance(CS.System.Type.GetType('System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[UnityEngine.Vector3, UnityEngine]],mscorlib'))
dic:Add('a', CS.UnityEngine.Vector3(1, 2, 3))
print(dic:TryGetValue('a'))
~~~
```
如果你的xLua版本大于v2.1.12,将会有更漂亮的表达方式
~~~lua
```lua
-- local List_String = CS.System.Collections.Generic['List<>'](CS.System.String) -- another way
local List_String = CS.System.Collections.Generic.List(CS.System.String)
local lst = List_String()
@ -314,7 +325,7 @@ local Dictionary_String_Vector3 = CS.System.Collections.Generic.Dictionary(CS.Sy
local dic = Dictionary_String_Vector3()
dic:Add('a', CS.UnityEngine.Vector3(1, 2, 3))
print(dic:TryGetValue('a'))
~~~
```
## 调用LuaEnv.Dispose时报“try to dispose a LuaEnv with C# callback!”错是什么原因?
@ -333,17 +344,17 @@ print(dic:TryGetValue('a'))
xlua提供了一个工具函数来帮助你找到被C#引用着的lua函数util.print_func_ref_by_csharp使用很简单执行如下lua代码
~~~lua
```lua
local util = require 'xlua.util'
util.print_func_ref_by_csharp()
~~~
```
可以看到控制台有类似这样的输出下面第一行表示有一个在main.lua的第2行定义的函数被C#引用着
~~~bash
```bash
LUA: main.lua:2
LUA: main.lua:13
~~~
```
## 调用LuaEnv.Dispose崩溃
@ -358,14 +369,14 @@ LUA: main.lua:13
用util.hotfix_ex可以调用原先的C#逻辑
~~~lua
```lua
local util = require 'xlua.util'
util.hotfix_ex(CS.HotfixTest, 'Add', function(self, a, b)
local org_sum = self:Add(a, b)
print('org_sum', org_sum)
return a + b
end)
~~~
```
## 怎么把C#的函数赋值给一个委托字段
@ -375,7 +386,7 @@ end)
比如如下C#代码
~~~csharp
```csharp
public class TestClass
{
public void Foo(int a)
@ -387,10 +398,10 @@ public class TestClass
}
public delegate void TestDelegate(int a);
~~~
```
你可以指明用Foo函数创建一个TestDelegate实例
~~~lua
```lua
local util = require 'xlua.util'
local d1 = util.createdelegate(CS.TestDelegate, obj, CS.TestClass, 'Foo', {typeof(CS.System.Int32)}) --由于Foo是实例方法所以参数2需要传TestClass实例
@ -398,7 +409,7 @@ local d2 = util.createdelegate(CS.TestDelegate, nil, CS.TestClass, 'SFoo', {type
obj_has_TestDelegate.field = d1 + d2 --到时调用field的时候将会触发Foo和SFoo这不会经过Lua适配
~~~
```
## 为什么有时Lua错误直接中断了而没错误信息
@ -408,15 +419,15 @@ obj_has_TestDelegate.field = d1 + d2 --到时调用field的时候将会触发Foo
把类似下面的代码:
~~~lua
```lua
coroutine.resume(co, ...)
~~~
```
改为:
~~~lua
```lua
assert(coroutine.resume(co, ...))
~~~
```
2、上层catch后不打印
@ -432,7 +443,7 @@ assert(coroutine.resume(co, ...))
可以通过xlua.tofunction结合反射来处理xlua.tofunction输入一个MethodBase对象返回一个lua函数。比如下面的C#代码
~~~csharp
```csharp
class TestOverload
{
public int Add(int a, int b)
@ -447,11 +458,11 @@ class TestOverload
return (short)(a + b);
}
}
~~~
```
我们可以这么调用指定重载:
~~~lua
```lua
local m1 = typeof(CS.TestOverload):GetMethod('Add', {typeof(CS.System.Int16), typeof(CS.System.Int16)})
local m2 = typeof(CS.TestOverload):GetMethod('Add', {typeof(CS.System.Int32), typeof(CS.System.Int32)})
local f1 = xlua.tofunction(m1) --切记对于同一个MethodBase只tofunction一次然后重复使用
@ -461,7 +472,7 @@ local obj = CS.TestOverload()
f1(obj, 1, 2) --调用short版本成员方法所以要传对象静态方法则不需要
f2(obj, 1, 2) --调用int版本
~~~
```
注意xlua.tofunction由于使用不太方便以及使用了反射所以建议做作为临时方案尽量用封装的方法来解决。
@ -511,3 +522,10 @@ f2(obj, 1, 2) --调用int版本
常见的不明显的多线程的场景比如c#异步socket,对象析构函数等。
## maOS10.15以上,启动unity的时候提示xlua.bundle损坏,移动到废纸篓
执行
```bash
sudo xattr -r -d com.apple.quarantine xlua.bundle
```

@ -3,67 +3,67 @@
## 总体
* Lua虚拟机支持
* Lua5.3
* Luajit2.1
* Lua5.3
* Luajit2.1
* Unity3D版本支持
* 各版本均支持
* 各版本均支持
* 平台支持
* windows 64/32
* android
* ios 64/32/bitcode
* osx
* uwp
* webgl
* windows 64/32
* android
* ios 64/32/bitcode
* osx
* uwp
* webgl
* 互访技术
* 生成适配代码
* 反射
* 生成适配代码
* 反射
* 易用性
* 解压即可用
* 开发期无需生成代码
* 生成代码和反射间可无缝切换
* 更简单的无GC api
* 菜单简单易懂
* 配置可以多份按模块划分也可以直接在目标类型上打Attribute标签
* 自动生成link.xml防止代码剪裁
* Plugins部分采用cmake编译更简单
* 核心代码不依赖生成代码,可以随时删除生成目录
* 解压即可用
* 开发期无需生成代码
* 生成代码和反射间可无缝切换
* 更简单的无GC api
* 菜单简单易懂
* 配置可以多份按模块划分也可以直接在目标类型上打Attribute标签
* 自动生成link.xml防止代码剪裁
* Plugins部分采用cmake编译更简单
* 核心代码不依赖生成代码,可以随时删除生成目录
* 性能
* Lazyload技术避免用不上的类型的开销
* lua函数映射到c# delegatelua table映射到interface可实现接口层面无C# gc alloc开销
* 所有基本值类型所有枚举字段都是值类型的struct在Lua和C#间传递无C# gc alloc
* LuaTableLuaFunction提供无gc访问接口
* 通过代码生成期的静态分析,生成最优代码
* 支持C#和Lua间指针传递
* 自动解除已经Destroy的UnityEngine.Object的引用
* Lazyload技术避免用不上的类型的开销
* lua函数映射到c# delegatelua table映射到interface可实现接口层面无C# gc alloc开销
* 所有基本值类型所有枚举字段都是值类型的struct在Lua和C#间传递无C# gc alloc
* LuaTableLuaFunction提供无gc访问接口
* 通过代码生成期的静态分析,生成最优代码
* 支持C#和Lua间指针传递
* 自动解除已经Destroy的UnityEngine.Object的引用
* 扩展性
* 不用改代码就可以加入Lua第三方扩展
* 生成引擎提供接口做二次开发
* 不用改代码就可以加入Lua第三方扩展
* 生成引擎提供接口做二次开发
## 支持为如下C#实现打补丁
* 构造函数
* 析构函数
* 成员函数
* 静态函数
* 泛化函数
* 操作符重载
* 成员属性
* 静态属性
* 事件
* 构造函数
* 析构函数
* 成员函数
* 静态函数
* 泛化函数
* 操作符重载
* 成员属性
* 静态属性
* 事件
## Lua代码加载
* 加载字符串
* 支持加载后立即执行
* 支持加载后返回一个delegate或者LuaFunction调用delegate或者LuaFunction后可传脚本参数
* 支持加载后立即执行
* 支持加载后返回一个delegate或者LuaFunction调用delegate或者LuaFunction后可传脚本参数
* Resources目录的文件
* 直接require
* 直接require
* 自定义loader
* Lua里头require时触发
* require参数透传给loaderloader读取Lua代码返回
* Lua里头require时触发
* require参数透传给loaderloader读取Lua代码返回
* Lua原有的方式
* Lua原有的方式都保留
* Lua原有的方式都保留
## Lua调用C#
* 创建C#对象
@ -72,58 +72,58 @@
* C#成员属性,字段
* C#成员方法
* C#继承
* 子类对象可以直接调用父类的方法,访问父类属性
* 子类模块可以直接调用父类的静态方法,静态属性
* 子类对象可以直接调用父类的方法,访问父类属性
* 子类模块可以直接调用父类的静态方法,静态属性
* 扩展方法Extension methods
* 就像普通成员方法一样使用
* 就像普通成员方法一样使用
* 参数的输入输出属性outref
* out对应一个lua返回值
* ref对应一个lua参数以及一个lua返回值
* out对应一个lua返回值
* ref对应一个lua参数以及一个lua返回值
* 函数重载
* 支持重载
* 由于lua数据类型远比C#要少,会出现无法判断的情况,可通过扩展方法来来调用。
* 支持重载
* 由于lua数据类型远比C#要少,会出现无法判断的情况,可通过扩展方法来来调用。
* 操作符重载
* 支持的操作符:+-*/==,一元-<<= %[]
* 其它操作符可以借助扩展方法调用
* 支持的操作符:+-*/==,一元-<<= %[]
* 其它操作符可以借助扩展方法调用
* 参数默认值
* C#参数有默认值在lua可以不传
* C#参数有默认值在lua可以不传
* 可变参数
* 在对应可变参数部分,直接输入一个个参数即可,不需要把这些参数扩到一个数组里头
* 在对应可变参数部分,直接输入一个个参数即可,不需要把这些参数扩到一个数组里头
* 泛化方法调用
* 静态方法可以自行封装使用
* 成员函数可通过扩展方法封装使用
* 静态方法可以自行封装使用
* 成员函数可通过扩展方法封装使用
* 枚举类型
* 数字或字符串到枚举的转换
* 数字或字符串到枚举的转换
* delegate
* 调用一个C# delegate
* +操作符
* -操作符
* 把一个lua函数作为一个c# delegate传递给c#
* 调用一个C# delegate
* +操作符
* -操作符
* 把一个lua函数作为一个c# delegate传递给c#
* event
* 增加事件回调
* 移除事件回调
* 增加事件回调
* 移除事件回调
* 64位整数
* 传递无gc而且无精度损失
* lua53下使用原生64位支持
* 可以和number运算
* 以java的方式支持无符号64位整数
* 传递无gc而且无精度损失
* lua53下使用原生64位支持
* 可以和number运算
* 以java的方式支持无符号64位整数
* table的自动转换到C#复杂类型
* obj.complexField = {a = 1, b = {c = 1}}obj是一个C#对象complexField是两层嵌套的struct或者class
* obj.complexField = {a = 1, b = {c = 1}}obj是一个C#对象complexField是两层嵌套的struct或者class
* typeof
* 对应C#的typeof操作符返回Type对象
* 对应C#的typeof操作符返回Type对象
* lua侧直接clone
* decimal
* 传递无gc而且无精度损失
* 传递无gc而且无精度损失
## C#调用Lua
* 调用Lua函数
* 以delegate方式调用Lua函数
* 以LuaFunction调用lua函数
* 以delegate方式调用Lua函数
* 以LuaFunction调用lua函数
* 访问Lua的table
* LuaTable的泛化Get/Set接口调用无gc可指明KeyValue的类型
* 用标注了CSharpCallLua的interface访问
* 值拷贝到structclass
* LuaTable的泛化Get/Set接口调用无gc可指明KeyValue的类型
* 用标注了CSharpCallLua的interface访问
* 值拷贝到structclass
## Lua虚拟机
@ -132,8 +132,8 @@
## 工具链
* Lua Profiler
* 可根据函数调用总时长,平均每次调用时长,调用次数排序
* 显示lua函数名及其所在文件的名字及行号
* 如果C#函数会显示这个是C#函数
* 可根据函数调用总时长,平均每次调用时长,调用次数排序
* 显示lua函数名及其所在文件的名字及行号
* 如果C#函数会显示这个是C#函数
* 支持真机调试

@ -1,32 +1,37 @@
## 简介
热补丁允许你使用 xLua 的代码逻辑, 替换掉原有的 C# 程序逻辑, 以实现热补丁.
## 使用方式
1、打开该特性
1. 打开该特性
添加HOTFIX_ENABLE宏在Unity3DFile->Build Setting->Scripting Define Symbols下添加。编辑器、各手机平台这个宏要分别设置如果是自动化打包要注意在代码里头用API设置的宏是不生效的需要在编辑器设置。
添加 `HOTFIX_ENABLE` 宏,(在 Unity3D 的 "File->Build Setting->Scripting Define Symbols" 下添加)。编辑器、各手机平台这个宏要分别设置!如果是自动化打包,要注意在代码里头用 API 设置的宏是不生效的,需要在编辑器设置。
建议平时开发业务代码不打开HOTFIX_ENABLE只在build手机版本或者要在编译器下开发补丁时打开HOTFIX_ENABLE
(建议平时开发业务代码不打开 `HOTFIX_ENABLE`,只在构建手机版本或者要在编译器下开发补丁时打开 `HOTFIX_ENABLE`
2、执行XLua/Generate Code菜单
2. 在菜单中找到 "XLua/Generate Code" 按钮并单击
3、注入,构建手机包这个步骤会在构建时自动进行,编辑器下开发补丁需要手动执行"XLua/Hotfix Inject In Editor"菜单。打印“hotfix inject finish!”或者“had injected!”才算成功,否则会打印错误信息。
3. 注入,构建手机包这个步骤会在构建时自动进行,编辑器下开发补丁需要手动执行 "XLua/Hotfix Inject In Editor" 菜单。打印 “hotfix inject finish!” 或者 “had injected!” 才算成功,否则会打印错误信息。
如果已经打印了“hotfix inject finish!”或者“had injected!”执行xlua.hotfix仍然报类似“xlua.access, no field __Hitfix0_Update”的错误要么是该类没配置到Hotfix列表要么是注入成功后又触发了编译覆盖了注入结果。
如果已经打印了 “hotfix inject finish!” 或者 “had injected!”,执行 `xlua.hotfix` 仍然报类似 “xlua.access, no field __Hitfix0_Update” 的错误,要么是该类没配置到 Hotfix 列表,要么是注入成功后,又触发了编译,覆盖了注入结果。
## 约束
## 局限性
不支持静态构造函数。
目前只支持Assets下代码的热补丁不支持引擎c#系统库的热补丁
目前只支持 Assets 下代码的热补丁,不支持引擎,C# 系统库的热补丁。
## API
xlua.hotfix(class, [method_name], fix)
`xlua.hotfix(class, [method_name], fix)`
* 描述 注入lua补丁
* class C#类两种表示方法CS.Namespace.TypeName或者字符串方式"Namespace.TypeName"字符串格式和C#的Type.GetType要求一致如果是内嵌类型Nested Type是非Public类型的话只能用字符串方式表示"Namespace.TypeName+NestedTypeName"
* method_name 方法名,可选;
* fix 如果传了method_namefix将会是一个function否则通过table提供一组函数。table的组织按key是method_namevalue是function的方式。
base(csobj)
`base(csobj)`
* 描述 子类override函数通过base调用父类实现。
* csobj 对象
@ -41,7 +46,7 @@ xlua.hotfix(CS.BaseTest, 'Foo', function(self, p)
end)
```
util.hotfix_ex(class, method_name, fix)
`util.hotfix_ex(class, method_name, fix)`
* 描述 xlua.hotfix的增强版本可以在fix函数里头执行原来的函数缺点是fix的执行会略慢。
* method_name 方法名;
@ -53,9 +58,13 @@ util.hotfix_ex(class, method_name, fix)
方式一直接在类里头打Hotfix标签不建议示例只是为了方便演示采取这种方式
方式二在一个static类的static字段或者属性里头配置一个列表。属性可以用于实现的比较复杂的配置比如根据Namespace做白名单。
!!注意,方式一在高版本 Unity 不支持
~~~csharp
方式二:在一个静态类的静态字段或者属性里头配置一个列表。属性可以用于实现的比较复杂的配置,比如根据命名空间做白名单。
!!注意,高版本 Unity 需要把配置文件放 Editor 目录下
```csharp
//如果涉及到Assembly-CSharp.dll之外的其它dll如下代码需要放到Editor目录
public static class HotfixCfg
{
@ -77,7 +86,7 @@ public static class HotfixCfg
}
}
}
~~~
```
## Hotfix Flag
@ -85,37 +94,37 @@ Hotfix标签可以设置一些标志位对生成代码及插桩定制化
* Stateless、Stateful
遗留设置Stateful方式在新版本已经删除因为这种方式可以用xlua.util.state接口达到类似的效果该接口的使用可以看下HotfixTest2.cs里的示例代码。
遗留设置,`Stateful` 方式在新版本已经删除,因为这种方式可以用 `xlua.util.state` 接口达到类似的效果,该接口的使用可以看下`HotfixTest2.cs` 里的示例代码。
由于没Stateful默认就是Stateless所以也没必要设置该标志位。
由于没 `Stateful`,默认就是 `Stateless`,所以也没必要设置该标志位。
* ValueTypeBoxing
值类型的适配delegate会收敛到object好处是代码量更少不好的是值类型会产生boxing及gc适用于对text段敏感的业务。
值类型的适配delegate会收敛到object好处是代码量更少不好的是值类型会产生boxing及gc适用于对text段敏感的业务。
* IgnoreProperty
不对属性注入及生成适配代码,一般而言,大多数属性的实现都很简单,出错几率比较小,建议不注入。
不对属性注入及生成适配代码,一般而言,大多数属性的实现都很简单,出错几率比较小,建议不注入。
* IgnoreNotPublic
不对非public的方法注入及生成适配代码。除了像MonoBehaviour那种会被反射调用的私有方法必须得注入其它仅被本类调用的非public方法可以不注入只不过修复时会工作量稍大所有引用到这个函数的public方法都要重写。
不对非public的方法注入及生成适配代码。除了像MonoBehaviour那种会被反射调用的私有方法必须得注入其它仅被本类调用的非public方法可以不注入只不过修复时会工作量稍大所有引用到这个函数的public方法都要重写。
* Inline
不生成适配delegate直接在函数体注入处理代码。
不生成适配 delegate直接在函数体注入处理代码。
* IntKey
不生成静态字段,而是把所有注入点放到一个数组集中管理。
不生成静态字段,而是把所有注入点放到一个数组集中管理。
好处对text段影响小。
好处:对 text 段影响小。
坏处使用不像默认方式那么方便需要通过id来指明hotfix哪个函数而这个id是代码注入工具时分配的函数到id的映射会保存在Gen/Resources/hotfix_id_map.lua.txt并且自动加时间戳备份到hotfix_id_map.lua.txt同级目录发布手机版本后请妥善保存该文件。
坏处使用不像默认方式那么方便需要通过id来指明hotfix哪个函数而这个id是代码注入工具时分配的函数到id的映射会保存在 `Gen/Resources/hotfix_id_map.lua.txt`,并且自动加时间戳备份到 `hotfix_id_map.lua.txt` 同级目录,发布手机版本后请妥善保存该文件。
该文件的格式大概如下注意该文件仅IntKey模式使用当你没类型指定IntKey模式注入该文件只返回个空表
该文件的格式大概如下注意该文件仅IntKey模式使用当你没类型指定IntKey模式注入该文件只返回个空表
~~~lua
```lua
return {
["HotfixTest"] = {
[".ctor"] = {
@ -138,19 +147,19 @@ return {
},
},
}
~~~
```
想要替换HotfixTestUpdate函数你得
想要替换 `HotfixTest``Update` 函数,你得
~~~lua
```lua
CS.XLua.HotfixDelegateBridge.Set(7, func)
~~~
```
如果是重载函数将会一个函数名对应多个id比如上面的Add函数。
如果是重载函数,将会一个函数名对应多个 id比如上面的 `Add` 函数。
能不能自动化一些呢可以xlua.util提供了auto_id_map函数执行一次后你就可以像以前那样直接用类方法名去指明修补的函数。
能不能自动化一些呢?可以,`xlua.util` 提供了 `auto_id_map` 函数,执行一次后你就可以像以前那样直接用类,方法名去指明修补的函数。
~~~lua
```lua
(require 'xlua.util').auto_id_map()
xlua.hotfix(CS.HotfixTest, 'Update', function(self)
self.tick = self.tick + 1
@ -158,25 +167,24 @@ xlua.hotfix(CS.HotfixTest, 'Update', function(self)
print('<<<<<<<<Update in lua, tick = ' .. self.tick)
end
end)
~~~
前提是hotfix_id_map.lua.txt放到可以通过require 'hotfix_id_map'引用到的地方
```
前提是 `hotfix_id_map.lua.txt` 放到可以通过 `require 'hotfix_id_map'` 引用到的地方。
## 使用建议
* 对所有较大可能变动的类型加上Hotfix标识
* 建议用反射找出所有函数参数字段属性事件涉及的delegate类型标注CSharpCallLua
* 业务代码引擎API系统API需要在Lua补丁里头高性能访问的类型加上LuaCallCSharp
* 引擎API系统API可能被代码剪裁调C#无引用的地方都会被剪裁如果觉得可能会新增C#代码之外的API调用这些API所在的类型要么加LuaCallCSharp要么加ReflectionUse
* 对所有较大可能变动的类型加上 `Hotfix` 标识;
* 建议用反射找出所有函数参数、字段、属性、事件涉及的 delegate 类型,标注 `CSharpCallLua`
* 业务代码引擎 API系统 API需要在 Lua 补丁里头高性能访问的类型,加上 `LuaCallCSharp`
* 引擎 API系统 API 可能被代码剪裁调C#无引用的地方都会被剪裁),如果觉得可能会新增 C# 代码之外的 API 调用这些 API 所在的类型要么加 `LuaCallCSharp`,要么加 `ReflectionUse`
## 打补丁
xlua可以用lua函数替换C#的构造函数函数属性事件的替换lua实现都是函数比如属性对于一个getter函数和一个setter函数事件对应一个add函数和一个remove函数
xlua可以用lua函数替换 C# 的构造函数,函数,属性,事件的替换。lua实现都是函数比如属性对于一个 getter 函数和一个 setter 函数事件对应一个 `add` 函数和一个 `remove` 函数。
* 函数
method_name传函数名支持重载不同重载都是转发到同一个lua函数
`method_name` 传函数名,支持重载,不同重载都是转发到同一个 lua 函数
比如:
@ -207,41 +215,41 @@ end)
```
静态函数和成员函数的区别是成员函数会加一个self参数这个selfStateless方式下是C#对象本身对应C#的this
静态函数和成员函数的区别是成员函数会加一个 self 参数这个 selfStateless 方式下是 C# 对象本身(对应 C# 的 this
普通参数对于lua的参数ref参数对应lua的一个参数和一个返回值out参数对于lua的一个返回值
普通参数对于 lua 的参数ref 参数对应 lua 的一个参数和一个返回值out参数对于lua的一个返回值
泛化函数的打补丁规则和普通函数一样。
* 构造函数
构造函数对应的method_name".ctor"。
构造函数对应的 `method_name` 是 ".ctor"。
和普通函数不一样的是构造函数的热补丁并不是替换而是执行原有逻辑后调用lua。
* 属性
对于名为AProp的属性会对应一个gettermethod_name等于get_APropsettermethod_name等于set_AProp
对于名为 “AProp” 的属性,会对应一个 getter`method_name` 等于 `get_AProp`setter`method_name` 等于 `set_AProp`
* []操作符
赋值对应set_Item取值对应get_Item第一个参数是self赋值后面跟keyvalue取值只有key参数返回值是取出的值
赋值对应 `set_Item`取值对应 `get_Item`第一个参数是 self赋值后面跟 keyvalue取值只有 key 参数返回值是取出的值
* 其它操作符
C#的操作符都有一套内部表示比如+号的操作符函数名是op_Addition其它操作符的内部表示可以去请参照相关资料覆盖这函数就覆盖了C#的+号操作符
C#的操作符都有一套内部表示,比如 `+` 号的操作符函数名是 `op_Addition`其它操作符的内部表示可以去请参照相关资料覆盖这函数就覆盖了 C# 的 `+` 号操作符。
* 事件
比如对于事件AEvent”,+=操作符是add_AEvent-=对应的是remove_AEvent。这两个函数均是第一个参数是self第二个参数是操作符后面跟的delegate。
比如对于事件AEvent”+= 操作符是 add_AEvent-=对应的是 remove_AEvent。这两个函数均是第一个参数是self第二个参数是操作符后面跟的delegate。
通过xlua.private_accessible版本号大于2.1.11不需要调用xlua.private_accessible来直接访问事件对应的私有delegate的直接访问后可以通过对象的"&事件名"字段直接触发事件例如self\['&MyEvent'\]()其中MyEvent是事件名
通过 `xlua.private_accessible`版本号大于2.1.11不需要调用 `xlua.private_accessible`来直接访问事件对应的私有 delegate 的直接访问后可以通过对象的"&事件名"字段直接触发事件,例如 `self['&MyEvent']()`其中MyEvent是事件名
* 析构函数
method_name"Finalize"传一个self参数
method_name 是 "Finalize"传一个 self 参数
和普通函数不一样的是析构函数的热补丁并不是替换而是开头调用lua函数后继续原有逻辑
和普通函数不一样的是析构函数的热补丁并不是替换而是开头调用 lua 函数后继续原有逻辑
* 泛化类型
@ -253,10 +261,9 @@ public class GenericClass<T>
```
你只能对GenericClass\<double\>GenericClass\<int\>这些类而不是对GenericClass打补丁
你只能对 `GenericClass<double>``GenericClass<int>` 这些类,而不是对 `GenericClass` 打补丁。
对GenericClass<double>打补丁的实例如下:
`GenericClass<double>` 打补丁的实例如下:
```csharp
luaenv.DoString(@"
@ -277,9 +284,9 @@ luaenv.DoString(@"
* Unity协程
通过util.cs_generator可以用一个function模拟一个IEnumerator在里头用coroutine.yield就类似C#里头的yield return。比如下面的C#代码和对应的hotfix代码是等同效果的
通过 `util.cs_generator` 可以用一个 function 模拟一个 `IEnumerator`,在里头用 `coroutine.yield`,就类似 C# 里头的 yield return。比如下面的 C# 代码和对应的 hotfix 代码是等同效果的
~~~csharp
```csharp
[XLua.Hotfix]
public class HotFixSubClass : MonoBehaviour {
IEnumerator Start()
@ -291,9 +298,9 @@ public class HotFixSubClass : MonoBehaviour {
}
}
}
~~~
```
~~~csharp
```csharp
luaenv.DoString(@"
local util = require 'xlua.util'
xlua.hotfix(CS.HotFixSubClass,{
@ -307,11 +314,11 @@ luaenv.DoString(@"
end;
})
");
~~~
```
* 整个类
如果要替换整个类不需要一次次的调用xlua.hotfix去替换可以整个一次完成。只要给一个table按method_name = function组织即可
如果要替换整个类,不需要一次次的调用 `xlua.hotfix` 去替换,可以整个一次完成。只要给一个 table `method_name = function` 组织即可
```lua
@ -365,4 +372,3 @@ xlua.hotfix(CS.StatefullTest, {
})
```

@ -1,85 +1,55 @@
fileFormatVersion: 2
guid: 6b9f4e2e38c36db40bc5bdfe20038d94
timeCreated: 1481715979
licenseType: Pro
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
enableMipMap: 1
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 8
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: -1
wrapV: -1
wrapW: -1
wrapMode: -1
nPOTScale: 1
lightmap: 0
rGBM: 0
compressionQuality: 50
allowsAlphaSplitting: 0
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
spritePixelsToUnits: 100
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 1
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
textureType: -1
buildTargetSettings: []
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:

BIN
Assets/XLua/Doc/xLua.png Normal file

Binary file not shown.

After

(image error) Size: 28 KiB

@ -0,0 +1,56 @@
fileFormatVersion: 2
guid: b2926ca0864130e40b99cbe18d0fc395
timeCreated: 1481699971
licenseType: Pro
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 1
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 8
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 1
lightmap: 0
rGBM: 0
compressionQuality: 50
allowsAlphaSplitting: 0
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 0
textureType: -1
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant: