zoukankan      html  css  js  c++  java
  • NEO从入门到开窗(3)

    一、啰嗦两句

    第一节的时候咱说了C#编译完了之后,就该NEO的编译器搞事情了。我们完全可以按这个节奏搞,手动用NEO的编译器neon编译dll文件生成指令码文件.avm。但是NEO团队给我们写智能合约提供了个插件,咱们就先看看这玩意怎么玩,然后简单的介绍一下NEO的编译器源码。

    二、NeoContractPlugin

    咱在VS里【工具】-》【扩展和更新】里搜下NeoContractPlugin,安装这个模板。

    完事新建项目时候就能新建一个NeoContract的项目了

    创建完之后,就是这样滴。

    好,按NEO的模板创建出来的东东,多了build.tasks和Neo.ConvertTask.dll这俩文件,除此之外,在项目文件里还导入了一个project和AfterBuild之后的任务。这里做的事情,其实就是告诉项目编译完了之后跑一个ConvertTask的任务,看到项目里的Neo.ConvertTask.dll了么,后面我们介绍它。 

     

    ConvertTask这个任务是干嘛的,我们来看一眼源码,源码在项目neo-devpack-dotnet中

    using Microsoft.Build.Framework;
    using Microsoft.Build.Utilities;
    using System.Diagnostics;
    
    namespace Neo
    {
        /// <summary>
        /// this class generate config / xml file by template
        /// </summary>
        public class ConvertTask : Task
        {
            [Required]
            public ITaskItem DataSource { get; set; }
    
            /// <summary>
            /// execute replace logic
            /// </summary>
            /// <returns>ture successful, false failure</returns>
            public override bool Execute()
            {
                var srcdll = this.DataSource.ToString();
                string dllname = System.IO.Path.GetFileName(srcdll);
                ProcessStartInfo pinfo = new ProcessStartInfo();
                pinfo.FileName = "cmd.exe";
                pinfo.WorkingDirectory = System.IO.Path.GetDirectoryName(srcdll);
                pinfo.UseShellExecute = false;
                pinfo.RedirectStandardInput = true;
                pinfo.RedirectStandardOutput = true;
                pinfo.CreateNoWindow = true;
                pinfo.StandardOutputEncoding = System.Text.Encoding.UTF8;
    
                Process p = Process.Start(pinfo);
                p.StandardInput.AutoFlush = true;
                p.StandardInput.WriteLine("neon " + dllname);
                p.StandardInput.WriteLine("exit");
    
                //前四行后一行不要
                string lastline = null;
                int count = 0;
                bool bSucc = false;
                while (p.StandardOutput.EndOfStream == false)
                {
                    var line = p.StandardOutput.ReadLine();
                    count++;
                    if (count <= 4) continue;
    
                    if (lastline != null && lastline.Length > 0)
                    {
                        if (lastline[0] == '<')
                        {
                            if (lastline.IndexOf("<WARN>") == 0)
                            {
                                this.Log.LogWarning(lastline.Substring(6));
                                lastline = line;
                                continue;
                            }
                            else if (lastline.IndexOf("<ERR>") == 0)
                            {
                                this.Log.LogError(lastline.Substring(5));
                                lastline = line;
                                continue;
                            }
                            else if (lastline.IndexOf("<WARN|") == 0)
                            {
                                var l = lastline.Substring(6);
                                var ine = lastline.IndexOf(">");
                                var text = lastline.Substring(ine + 1);
                                var file = lastline.Substring(6, ine - 6);
                                var lines = file.Split(new char[] { '(', ')' });
                                int _line = 0;
                                if (lines.Length > 1)
                                {
                                    int.TryParse(lines[1], out _line);
                                }
                                this.Log.LogWarning("", "", "", lines[0], _line, 0, 0, 0, text);
                                lastline = line;
                                continue;
                            }
                            else if (lastline.IndexOf("<ERR|") == 0)
                            {
                                var l = lastline.Substring(5);
                                var ine = lastline.IndexOf(">");
                                var text = lastline.Substring(ine + 1);
                                var file = lastline.Substring(5, ine - 5);
                                var lines = file.Split(new char[] { '(', ')' });
                                int _line = 0;
                                if (lines.Length > 1)
                                {
                                    int.TryParse(lines[1], out _line);
                                }
                                this.Log.LogWarning("", "", "", lines[0], _line, 0, 0, 0, text);
                                lastline = line;
                                continue;
                            }
                        }
                        if (lastline.IndexOf("SUCC") == 0)
                        {
                            bSucc = true;
                        }
                        this.Log.LogMessageFromText(lastline, MessageImportance.High);
    
                    }
    
                    lastline = line;
                    //lines.Add(line);
                }
    
                //this.Log.LogMessageFromText(lastline, MessageImportance.High);
    
                p.WaitForExit();
                return bSucc;
            }
        }
    
    }
    ConvertTask

    好,先不管细节,就是起了一个cmd进程跑neon,其实就是帮我们调了一下NEO的编译器,妥了,那咱们就看看编译器搞了些撒事情吧。

    三、NEO编译器

    这一部分最好还是看看源码,我就简单介绍一下。这里有三个类比较关键:

    1. ModuleDefination: 这个类是用的库Mono.cecil,这个库可以查看或者修改IL文件,这里是官方地址:http://www.mono-project.com/docs/tools+libraries/libraries/Mono.Cecil/

    2. ILModule: 这个是编译器里定义的一个类,类的主要方法就是LoadModule,一看就明白了,其实现正是使用ModuleDefination加载并读取IL文件,将其转化为ILModule。这里其实还是用一种数据类型记录的智能合约代码的元数据信息,方法、字段、属性等的描述信息,可以理解成我们用反射操作类型。

    3. NeoModule: 这个是另外一个数据结构,通过一个ModuleConverter的类从ILModule逐条指令转化进NeoModule,这个结构里保持了一个有序字典,value就是转化后的指令码,也就是我们说的OpCode。之后就是把这个NeoModule Build成字节数组写入.avm文件。

    理解这三个类的含义就明白编译器的流程了。这里的难点是指令码,非常多,所以需要详细了解的自己看下源码吧。

    四、小结

    好了,今天就简单讲了一下NEO的智能合约模板背后都搞了啥,以及NEO编译器大概怎么编译的。通过前面几讲,大伙儿应该从工程的角度对NEO的智能合约这部分有些了解了。

    后续,准备从NEO的命令行全节点Neo-cli入手讲讲NEO的内部机制。

  • 相关阅读:
    LeetCode 226. Invert Binary Tree
    LeetCode 221. Maximal Square
    LeetCode 217. Contains Duplicate
    LeetCode 206. Reverse Linked List
    LeetCode 213. House Robber II
    LeetCode 198. House Robber
    LeetCode 188. Best Time to Buy and Sell Stock IV (stock problem)
    LeetCode 171. Excel Sheet Column Number
    LeetCode 169. Majority Element
    运维工程师常见面试题
  • 原文地址:https://www.cnblogs.com/DexterDi/p/8627621.html
Copyright © 2011-2022 走看看