热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

NEO从入门到开窗(3)NEO编译器

一、啰嗦两句第一节的时候咱说了C#编译完了之后,就该NEO的编译器搞事情了。我们完全可以按这个节奏搞,手动用NEO的编译器neon编译dll文件生成指令码文件.avm。但是NEO团

一、啰嗦两句

第一节的时候咱说了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
{
    /// 
    /// this class generate config / xml file by template
    /// 
    public class ConvertTask : Task
    {
        [Required]
        public ITaskItem DataSource { get; set; }

        /// 
        /// execute replace logic
        /// 
        /// ture successful, false failure
        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("") == 0)
                        {
                            this.Log.LogWarning(lastline.Substring(6));
                            lastline = line;
                            continue;
                        }
                        else if (lastline.IndexOf("") == 0)
                        {
                            this.Log.LogError(lastline.Substring(5));
                            lastline = line;
                            continue;
                        }
                        else if (lastline.IndexOf("") == 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("") == 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的内部机制。

NEO从入门到开窗(3) - NEO编译器


推荐阅读
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 在project.properties添加#Projecttarget.targetandroid-19android.library.reference.1..Sliding ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文总结了在开发中使用gulp时的一些技巧,包括如何使用gulp.dest自动创建目录、如何使用gulp.src复制具名路径的文件以及保留文件夹路径的方法等。同时介绍了使用base选项和通配符来保留文件夹路径的技巧,并提到了解决带文件夹的复制问题的方法,即使用gulp-flatten插件。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 本文记录了在vue cli 3.x中移除console的一些采坑经验,通过使用uglifyjs-webpack-plugin插件,在vue.config.js中进行相关配置,包括设置minimizer、UglifyJsPlugin和compress等参数,最终成功移除了console。同时,还包括了一些可能出现的报错情况和解决方法。 ... [详细]
  • 本文介绍了在Mac上安装Xamarin并使用Windows上的VS开发iOS app的方法,包括所需的安装环境和软件,以及使用Xamarin.iOS进行开发的步骤。通过这种方法,即使没有Mac或者安装苹果系统,程序员们也能轻松开发iOS app。 ... [详细]
author-avatar
零乱772_553
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有