Xlua 生成wrap文件
目錄:Xlua源碼學習
鏈接:https://pan.baidu.com/s/1ocCLzA5eEONs-032wRD5Zw
提取碼:zkqu
xlua通過模板文件批量生成c#文件這塊還是挺有意思的,建議把前面鏈接的lua生成代碼下載下來看一下。
具體的生成流程是:
1.Generator收集這種類型需要導出的對象。
2.通過LuaTemplate把對應的.tpl.txt文件轉成可執行的lua代碼。
3.在GenOne方法里給上一步生成的lua代碼賦值全局變量。
4.執行lua代碼生成wrap文件。
注:tolua的生成文件是ToLuaExport.cs。
核心文件:
1. c#的TemplateEngine、Generator文件。TemplateEngine負責處理通過正則方法把.tpl文件內容轉成可執行的lua代碼段(lua_wrap生成器),該生成器負責生成對應的文件,如wrapDelegateBridge等文件,最后轉成的生成代碼帶上面的鏈接里。Generator負責查找并分類要導出類型(類、枚舉、事件、委托)、按步驟生成文件。
2. lua的TemplateCommon文件,主要對上面的lua_wrap生成器所需要的一些公共方法進行封裝。例如通過類名查找類的全稱等,是一個提供輔助功能的文件。
3. 模板文件,XLuaSrcEditorTemplate下的tpl文件。這個是生成模板文件,GCM文件貌似沒用到。
LuaClassWrap:負責所有類的wrap的生成。
LuaDelegateBridge:生成DelegateGensBridge文件。封裝了對委托、事件的處理,提供了委托的生成器GetDelegateByType。委托工廠。
LuaEnumWrap:EnumWrap文件生成器。搜集了所有要導出的枚舉,枚舉是值類型,做個特殊處理。
LuaInterfaceBridge:搜索Bridge : LuaBase,基本沒用到,用于Interface的wrap生成。
LuaRegister:XLua_Gen_Initer_Register__文件生成,該文件收集了所有wrap文件并注冊到ObjectTranslator的delayWrap里供類的初始化使用。
LuaWrapPusher:生成WrapPusher文件,主要還是對Vector2等結構體的pushgetset進行一個封裝。
PackUnpack:生成CopyByValue文件,該對unity的vectorcolor等結構體與lua之間進行轉換。
具體文件分析:
1.TemplateEngine:
正則匹配表達式:
static string GetRegexString()
{
//分組,實際匹配((?!<%).)*%>
//"?="正向預查:字符串后面的字符(串)進行限定。指定能夠出現的字符(串)。
//"?!"負正向預查:對字符串后面的字符(串)進行限定,指定不能夠出現的字符(串)。
string regexBadUnopened = @"(?<error>((?!<%).)*%>)";//
string regexText = @"(?<text>((?!<%).)+)";
string regexNoCode = @"(?<nocode><%=?%>)";
string regexCode = @"<%(?<code>[^=]((?!<%|%>).)*)%>";
string regexEval = @"<%=(?<eval>((?!<%|%>).)*)%>";
string regexBadUnclosed = @"(?<error><%.*)";
string regexBadEmpty = @"(?<error>^$)";
return '(' + regexBadUnopened
+ '|' + regexText
+ '|' + regexNoCode
+ '|' + regexCode
+ '|' + regexEval
+ '|' + regexBadUnclosed
+ '|' + regexBadEmpty
+ ")*";
}
如下,通過正則匹配后的字符串處理如下:
1.Text匹配的是c#的類的內容,這邊直接是當成字符串。在lua生成器對應的是
table.insert(__text_gen, "
public ")
2.Eval意思是要用lua的變量替代該內容,對應如下:
table.insert(__text_gen, tostring(return_type_name))
3.Code是lua的可執行內容。
如果對正則不是很清楚,可以直接在ComposeCode方法返回前打斷點,可以看到最終要執行的lua代碼。
public static string ComposeCode(List<Chunk> chunks)
{
StringBuilder code = new StringBuilder();
code.Append("local __text_gen = {}
");
foreach (var chunk in chunks)
{
switch (chunk.Type)
{
case TokenType.Text:
code.Append("table.insert(__text_gen, "" + chunk.Text + "")
");
break;
case TokenType.Eval:
code.Append("table.insert(__text_gen, tostring(" + chunk.Text + "))
");
break;
case TokenType.Code:
code.Append(chunk.Text + "
");
break;
}
}
code.Append("return table.concat(__text_gen)
");
string codeSSStr = code.ToString();
return code.ToString();
}
2.Generator:
1.在構造函數里獲取配置文件TemplateRef(文件的生成模板)及TemplateCommon的加載方法。
2.GenAll方法:
3.核心方法GenOne,所有lua生成器都是在這邊啟動的。
通過LuaTemplate.Compile把模板文件.tpl.txt文件轉成可執行的lua代碼并加載進內存。
type_info_getter(type, type_info);設置lua代碼要用到的參數。
LuaTemplate.Execute(template, type_info):執行lua代碼進行文件生成。
Execute方法中,會把前面的type_info設置成要執行代碼段的環境變量,即parameters的變量是compiledTemplate的全局變量。
public static string Execute(LuaFunction compiledTemplate, LuaTable parameters)
{
compiledTemplate.SetEnv(parameters);
object[] result = compiledTemplate.Call();
System.Diagnostics.Debug.Assert(result.Length == 1);
return result[0].ToString();
}
4.GenDelegateBridge方法:生成DelegatesGensBridge.cs文件。
5.GenEnumWrap方法:生成EnumWrap.cs文件。
6.類、接口Interface的Wrap生成、c#和lua的關于vector等結構體的轉換封裝。
public static void Gen(IEnumerable<Type> wraps, IEnumerable<Type> gc_optimze_list, IEnumerable<Type> itf_bridges, string save_path)
{
templateCache.Clear();
Directory.CreateDirectory(save_path);
GenWrap(wraps, save_path);//生成類的xxxWrap文件
GenWrapPusher(gc_optimze_list.Concat(wraps.Where(type=>type.IsEnum)).Distinct(), save_path);
GenPackUnpack(gc_optimze_list.Where(type => !type.IsPrimitive && SizeOf(type) != -1), save_path);
GenInterfaceBridge(itf_bridges, save_path);
}
public static void GenCodeForClass(bool minimum = false)
{
var warp_types = minimum ? new List<Type>() : LuaCallCSharp;
var itf_bridges_types = CSharpCallLua.Where(type => type.IsInterface).Distinct();
Gen(warp_types, GCOptimizeList, itf_bridges_types, GeneratorConfig.common_path);
}
7.GenLuaRegister:生成XLuaGenAutoRegister.cs文件,這個文件用于運行時找到對應類型的wrap文件,并執行該文件的__Registera方法,這個方法會把這個類的靜態方法(BeginClassRegister)、成員方法(BeginObjectRegister)注冊到lua表里。
總結
以上是生活随笔為你收集整理的Xlua 生成wrap文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAXBContext处理CDATA
- 下一篇: 【IT之家评测室】七彩虹 iGame G