plainchant
  • Welcome PCT‘s Blog
  • Golang
    • golang基础
      • Go 语言 select 的实现原理
      • golang数字最大值
      • go-defer
      • Channel实现
      • go逃逸分析
      • Golang调度
  • Linux
  • Linux开发
    • 查看磁盘的UUID并挂载
    • Linux内核开发示例
    • 误删Linux内核后修复系统
    • linux补丁的创建和应用
    • Git常用命令
    • SystemV消息队列使用范例
    • ubuntu搭建全局代理
    • linux安装和配置
  • 嵌入式
    • 计算机为什么存在补码
    • 一种可靠串口协议
    • CRC校验算法
    • RasperryPi3 Ros系统安装(Debian)
  • 套接字编程
    • TCP建立连接过程分析
    • 线程的分发
    • TCP的并发处理epoll
    • TCP的并发处理select
    • 非阻塞TCP示例
    • 阻塞TCP示例
    • UDP组播
    • UDP广播
    • 非阻塞UDP示例(fcntl方式)
    • 非阻塞UDP示例
    • 局域网发现协议
    • socket通信机制浅析-前言
  • 交友网站
  • 区块链
    • Wasm虚拟机
      • wagon外部参数和内部参数的统一
      • Wagon实现log函数的第二种方法
      • Wagon实现一个log函数
      • go版本wasm解析器分析
      • 解析wasm二进制文件
      • ONT实现API的流程
      • Wasm工具安装使用
    • BCH
      • SLP代币协议
    • Cosmos
      • 区块链共识进化史
      • Tendermint 的区块构成
      • CoinEx 链 Gas 费指南
      • CoinEx交易类型收集
      • Cosmos简介和环境搭建
    • ETH
      • Geth命令详解
    • BTC
      • 助记词到地址
  • 算法
    • 动态规划
  • HTTP
    • URL 在浏览器被被输入到页面展现的过程中发生了什么
  • 运维后台
    • Docker学习笔记
  • 数据型应用系统设计
    • 数据密集型应用系统设计读书笔记
    • 数据编码与演化
      • Kafka配置
      • protobuf简介
    • MySQL
      • mysql安装和数据目录变更
      • 深入理解事务
      • MySQL事务问题验证
    • Redis
      • Redis缓存实现
      • Redis基本概念
由 GitBook 提供支持
在本页
  • host接口
  • 外部导入部分
  • resolveImports中解决引用的方法
  • importer方式解决引用

这有帮助吗?

  1. 区块链
  2. Wasm虚拟机

Wagon实现log函数的第二种方法

[TOC]

前面我们介绍了一种实现方法,是自己构造function的方式,第二种其实也是一样的方式,通过构造env模块跳过外部引用,但是更符合项目的设计规范,wagon在设计之初就预留了host接口,作为本地函数实现接口,我们可以通过这个接口实现env模块的导入。

host接口

在创建新的虚拟机时,下面代码实现host‘的导入:

func NewVM(module *wasm.Module) (*VM, error) {
   var vm VM
   vm.funcs = make([]function, len(module.FunctionIndexSpace))
   vm.globals = make([]uint64, len(module.GlobalIndexSpace))
   vm.newFuncTable()
   vm.module = module
   nNatives := 0   for i, fn := range module.FunctionIndexSpace {      if fn.IsHost() {
         vm.funcs[i] = goFunction{
            typ: fn.Host.Type(),            val: fn.Host,         }
         nNatives++
         continue      }

如果函数是host类型,则直接添加到函数索引空间并且不再继续往下执行,那么就需要在解析外部引用时将函数设置为host类型。

外部导入部分

这里有两种方式,一种就是和我们在前面介绍的方法相同,在resolveImports函数中通过外部导入的包名引入函数,还有一种方式是通过main中的importer函数实现导入,两种方式都可以实现,前者是侵入式的更改,不过更简单,后者是非侵入式的更改,如果是引用wagon代码,可以考虑使用第二种。

resolveImports中解决引用的方法

func (module *Module) resolveImports(resolve ResolveFunc) error {
   if module.Import == nil {
      return nil
   }
   modules := make(map[string]*Module)
   native  := NewNativeFun()
   var funcs uint32   for _, importEntry := range module.Import.Entries {
      //TODO import/global/memory      if importEntry.ModuleName == "env" {
         switch importEntry.Kind {
            case ExternalFunction:
            funcType := module.Types.Entries[importEntry.Type.(FuncImport).Type]
            host := native.GetValue(importEntry.FieldName)
            fn := &Function{Sig: &FunctionSig{ParamTypes: funcType.ParamTypes, ReturnTypes: funcType.ReturnTypes}, Body: &FunctionBody{}, Host:host}
            module.FunctionIndexSpace = append(module.FunctionIndexSpace, *fn)
            module.Code.Bodies = append(module.Code.Bodies, *fn.Body)
            module.imports.Funcs = append(module.imports.Funcs, funcs)
            funcs++
            }
      }

当外部模块是env时,我们定义了一个新的Function对象,并且定义了它的Host字段,现在它就成为了一个host的方法,然后将这个方法添加到函数索引空间即可。这个host是我们自行定义的函数的类型反射:reflect.ValueOf(i),go语言可以通过反射知道这个函数的类型,从而调用到这个函数。

importer方式解决引用

func mImporter(name string) (*wasm.Module, error) {
   fmt.Println("import name:", name)
   m := wasm.NewModule()
   m.Types = &wasm.SectionTypes{      Entries: []wasm.FunctionSig{
         {
            Form:        0,            ParamTypes:  []wasm.ValueType{wasm.ValueTypeI32},            ReturnTypes: []wasm.ValueType{wasm.ValueTypeI32},         },      },   }
   m.FunctionIndexSpace = []wasm.Function{
      {
         Sig:  &m.Types.Entries[0],         Host: reflect.ValueOf(add3),         Body: &wasm.FunctionBody{},      },   }
   m.Export = &wasm.SectionExports{
      Entries: map[string]wasm.ExportEntry{
         "add3": {
            FieldStr: "add3",            Kind:     wasm.ExternalFunction,            Index:    0,         },   }
   return m, nil
}

其实解决思路是一样的,也是通过Host字段实现本地函数,然后通过反射注册函数类型,这种方式相对来说更繁琐一点。

上一页wagon外部参数和内部参数的统一下一页Wagon实现一个log函数

最后更新于4年前

这有帮助吗?