zoukankan      html  css  js  c++  java
  • L#脚本语言,直接把DLL当脚本执行(图解说明)

    L#是什么:Run DLL as a Script.

    A Pure C# IL Runner,直接解析执行IL的脚本引擎。

    从原理上讲是模拟执行了CLR的工作,从表现上讲就是把DLL作为资源直接加载执行。

    是不是很多同学梦寐以求的热更DLL能热更,但不是你想的那个热更。

    直接以反射符号的方式加载DLLDLL的解释执行还是由CLR完成的。还会涉及JIT引擎。
    但是L#"模拟"CLR的工作。不使用反射加载符号,不使用JIT
    IOSUnity)、WP8这样的平台,CLR就没反射加载符号这样的功能。IOS还关闭了JIT
    L#
    不受这个制约

    但是就带来了其他制约:交互上的一些麻烦

    主要记住这一条:L#加载的DLL中的代码属于脚本代码,和系统代码中的程序不能互相继承

    L#的语法是什么样的:

    L# 是直接运行dotnet 的DLL, 你可以用c# vb.net f# 等。只要能通过编译。
    与C#Light自己实现语法解释问题不同,L#没有语法解释层面的bug,只会有执行层面的bug。
    恰恰是C#Light在语法解释器的维护上陷入泥潭以后,深刻反思,才有了L#这个创意。

    关于代码:

    可以在http://svn.cltri.com 取得最新代码
    或者https://github.com/lightszero/lsharp
    目前还处于Alpha阶段,Bug是少不了的,这个阶段仅建议动手能力比较强的同学试用。
    发现BUG骂我是肯定要骂的,如果骂完之后,能够在Github上推一个错误用例
    将不甚感激。

     

    下面介绍一下L#在Unity3D的使用办法

    一步一步是这样,是魔鬼的步伐

    L#ForUnity3D Hell#oworld环境建立图解

    1.创建新项目

    2.Copy L#forU3D的类库到DLL中

    或者直接插入L#forU3D的源码也可以,自选

    3.创建一个代码供L#模块访问)

    剽窃了庞麦郎的歌词,但我是不会道歉的

    4.创建一个L#模块

    5.添加L#模块的引用

    因为我们刚才在plugins目录下创建的代码Interface.cs,希望L#模块访问他,就对应Assembly-Csharp-firstpass这个模块

    6.编写L#模块

    可以看到L#模块粗犷的调用了我们的程序

    然后F7,你会得到L#模块的dll文件

    7.把模块文件作为资源放进Unity3D

    把模块文件改名为

    HotFixCode.Dll.bytes

    HotFixCode.Pdb.bytes

    pdb这个文件不是必须的,但是当脚本出异常,你需要查一下是哪个文件哪一行出错的时候,没有pdb是查不出来的。只能给你一个干巴巴的地址。

    当然你熟悉IL的话,自己用别的工具,根据这个地址也是可以找到代码位置的。

    他在Unity里面应该被识别为两个TextAsset

    8.编写测试程序Test001

    新建场景并保存Test001,

    新建Test001脚本直接挂接到摄像机上

    编写代码如下:

    using UnityEngine;

    using System.Collections;

     

    public class test001 : MonoBehaviour {

     

        CLRSharp.CLRSharp_Environment env ;

        // Use this for initialization

        void Start () {

            //创建CLRSharp环境

            env=new CLRSharp.CLRSharp_Environment(new Logger());

        }

        

        // Update is called once per frame

        void Update () {

        

        }

        public class Logger:CLRSharp.ICLRSharp_Logger//实现L#的LOG接口

        {

            public void Log (string str)

            {

                Debug.Log (str);

            }

            

            public void Log_Error (string str)

            {

                Debug.LogError (str);

            }

            

            public void Log_Warning (string str)

            {

                Debug.LogWarning (str);

            }

        }

    }

    9.执行HelloWorld

    进入Unity,运行项目

    这是唯一的结果,有一条Log L#被初始化了

    L#HelloWorld 第二步,调用L#模块图解

    继续增加代码

     

    在Start函数后增加代码

    0.加载模块

            //加载L#模块
            TextAsset dll = Resources.Load("HoxFixCode.dll") as TextAsset;
            TextAsset pdb = Resources.Load("HoxFixCode.pdb") as TextAsset;
            System.IO.MemoryStream msDll = new System.IO.MemoryStream (dll.bytes);
            System.IO.MemoryStream msPdb = new System.IO.MemoryStream (pdb.bytes);
            //env.LoadModule (msDll, null);//不需要pdb的话,第二个参数传null
            env.LoadModule (msDll, msPdb);

    1.创建线程上下文

    2.取得准备调用的类型

    3.调用静态函数

    4.调用成员函数

    完整的start函数代码

        void Start () {

            //创建CLRSharp环境

            env=new CLRSharp.CLRSharp_Environment(new Logger());

     

            //加载L#模块

            TextAsset dll = Resources.Load("HoxFixCode.dll") as TextAsset;

            TextAsset pdb = Resources.Load("HoxFixCode.pdb") as TextAsset;

            System.IO.MemoryStream msDll = new System.IO.MemoryStream (dll.bytes);

            System.IO.MemoryStream msPdb = new System.IO.MemoryStream (pdb.bytes);

            //env.LoadModule (msDll, null);//不需要pdb的话,第二个参数传null

            env.LoadModule (msDll, msPdb);

            Debug.Log ("LoadModule HotFixCode.dll done.");

     

            //step01建立一个线程上下文,用来模拟L#的线程模型,每个线程创建一个即可。

            CLRSharp.ThreadContext context = new CLRSharp.ThreadContext (env);

            Debug.Log ("Create ThreadContext for L#.");

     

            //step02取得想要调用的L#类型

            CLRSharp.ICLRType wantType = env.GetType ("HoxFixCode.TestClass",null);//用全名称,包括命名空间

            Debug.Log ("GetType:"+wantType.Name);

            //和反射代码中的Type.GetType相对应

     

            //step03 静态调用

            //得到类型上的一个函数,第一个参数是函数名字,第二个参数是函数的参数表,这是一个没有参数的函数

            CLRSharp.IMethod method01 = wantType.GetMethod("Test1",CLRSharp.MethodParamList.MakeEmpty());

            method01.Invoke (context, null, null);//第三个参数是object[] 参数表,这个例子不需要参数

            //这是个静态函数调用,对应到代码他就是HotFixCode.TestClass.Test1();

     

            //step04 成员调用

            //第二个测试程序是一个成员变量,所以先要创建实例

            CLRSharp.CLRSharp_Instance typeObj = new CLRSharp.CLRSharp_Instance (wantType as CLRSharp.ICLRType_Sharp);//创建实例

            CLRSharp.IMethod methodctor = wantType.GetMethod(".ctor",CLRSharp.MethodParamList.MakeEmpty());//取得构造函数

            methodctor.Invoke (context, typeObj, null);//执行构造函数

            //这几行的作用对应到代码就约等于 HotFixCode.TestClass typeObj =new HotFixCode.TestClass();

            CLRSharp.IMethod method02 = wantType.GetMethod("Test2",CLRSharp.MethodParamList.MakeEmpty());

            method02.Invoke (context, typeObj, null);

            //这两行的作用就相当于 typeOBj.Test2();

        }

    执行结果

  • 相关阅读:
    python课堂练习
    Python爬虫学习笔记(九)——Selenium的使用
    Python爬虫学习笔记(八)——智高考数据爬取
    Python爬虫学习笔记(七)——Ajax
    Python爬虫学习笔记(六)——BeautifulSoup和pyquery的使用
    Python爬虫学习笔记(五)——XPath的使用
    Python爬虫学习笔记(四)——猫眼电影Top100
    Python爬虫学习笔记(三)——正则表达式
    Python爬虫学习笔记(二)——requests库的使用
    Python爬虫学习笔记(一)——urllib库的使用
  • 原文地址:https://www.cnblogs.com/crazylights/p/4216913.html
Copyright © 2011-2022 走看看