• 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表里。

  • 相关阅读:
    第二周总结
    个人总结
    软件设计模式7
    软件设计模式6
    软件设计模式5
    软件设计模式4
    软件设计模式3
    软件设计模式2
    软件设计模式1
    软件构造2
  • 原文地址:https://www.cnblogs.com/wang-jin-fu/p/13508720.html
Copyright © 2020-2023  润新知