wasm 在web中最小胶水代码; 报错Imports argument must be present and must be an object

加载和运行 WebAssembly 代码 我试过了没成功,代码裁剪有点严重

加载WebAssembly的两个新的API

新的 WebAssembly.compileStreaming/WebAssembly.instantiateStreaming 方法更加高效——它们直接在来自网络的原始字节流上执行操作,省去了 ArrayBuffer 步骤。

老的 WebAssembly.compile/WebAssembly.instantiate 方法要求你在获取原始字节之后创建一个包含了你的 WebAssembly 模块二进制的 ArrayBuffer,然后编译/实例化它。这类似于 new Function(string),只不过我们用字节数组缓冲区(WebAssembly 源码)替换了字符串(JavaScript 源码)。

调用时候的报错
在这里插入图片描述

环境是vite启动的服务

axios({
  url: '/test.wasm', // 拷贝文件到public
  method: 'get',
  responseType: 'stream' // 响应返回stream的类型
}).then(async (res) => {
// WebAssembly.instantiateStreaming()  介绍
// 函数直接从流式底层源编译并实例化 WebAssembly 模块。这是加载 Wasm 代码的最有效、最优化的方式。 
    const module = await WebAssembly.instantiateStreaming(
        res.data,
        // importObject // 需要这个对象但mdn 没有给出来
    )
    console.log(module.instance.exports)
})

在胶水代码中找到的

  var HEAP,
/** @type {!Int8Array} */
  HEAP8,
/** @type {!Uint8Array} */
  HEAPU8,
/** @type {!Int16Array} */
  HEAP16,
/** @type {!Uint16Array} */
  HEAPU16,
/** @type {!Int32Array} */
  HEAP32,
/** @type {!Uint32Array} */
  HEAPU32,
/** @type {!Float32Array} */
  HEAPF32,
/** @type {!Float64Array} */
  HEAPF64;
function _emscripten_memcpy_big(dest, src, num) {
  HEAPU8.copyWithin(dest, src, src + num);
}

  function _fd_write(fd, iov, iovcnt, pnum) {
    // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0
    var num = 0;
    for (var i = 0; i < iovcnt; i++) {
      var ptr = HEAPU32[((iov)>>2)];
      var len = HEAPU32[(((iov)+(4))>>2)];
      iov += 8;
      for (var j = 0; j < len; j++) {
        printChar(fd, HEAPU8[ptr+j]);
      }
      num += len;
    }
    HEAPU32[((pnum)>>2)] = num;
    return 0;
  }


var wasmImports = {
  "emscripten_memcpy_big": _emscripten_memcpy_big,
  "fd_write": _fd_write
};
var info = {
    'env': wasmImports,
    'wasi_snapshot_preview1': wasmImports,
  };

const module = WebAssembly.instantiateStreaming(
    fetch('/test.wasm'),
    info
    ).then(res=>{
      console.log(res)
})

_fd_write函数某个工具给出来的解释参考 感觉就是提取wasm里的被导出来的函数吧

这段代码是一个低级函数,其目的是模拟文件描述符(fd)上的写操作。这是通过遍历输入的iov(即输入的“I/O向量”)数组,并将其内容写入文件描述符fd来实现的。
让我们详细地分析一下这段代码:
iov 是一个指针,指向一个包含多个iovec结构的数组。每个iovec结构包含两个成员:一个指向数据的指针和该数据的长度。
iovcnt 是iov数组中的元素数量。
_fd_write 函数遍历iov数组,处理每个iovec,并将其内容写入文件描述符fd。
对于每个iovec,它首先获取数据的指针(即内存地址)和长度。然后,它使用这些信息从内存中读取数据,并将其逐个字符地写入文件描述符。
函数最后将写入的字符数存储在pnum指向的位置。
函数返回0,表示写操作成功完成。
注意:这个代码片段是用JavaScript写的,并且可能是模拟或模拟器的一部分,特别是针对系统级编程或低级编程。
另外,这段代码似乎是从更大的上下文中提取出来的,因为它引用了几个变量(如 HEAPU8 和 HEAPU32),这些变量在给定的代码片段中没有定义。这些变量可能是指向特定类型数组的指针,这些数组用于模拟系统级别的数据结构或内存布局。

控制台成功打印出对象包含了我导出的int_sqrt、main

运行成功导出的两个函数 main 和int_sqrt
较完整的代码

<script setup>
// import axios from 'axios';  // 用axios 请求的方式也可以
import { onMounted } from 'vue';

onMounted(async ()=>{
  var HEAP,
/** @type {!Int8Array} */
  HEAP8,
/** @type {!Uint8Array} */
  HEAPU8,
/** @type {!Int16Array} */
  HEAP16,
/** @type {!Uint16Array} */
  HEAPU16,
/** @type {!Int32Array} */
  HEAP32,
/** @type {!Uint32Array} */
  HEAPU32,
/** @type {!Float32Array} */
  HEAPF32,
/** @type {!Float64Array} */
  HEAPF64;
function _emscripten_memcpy_big(dest, src, num) {
  HEAPU8.copyWithin(dest, src, src + num);
}

  function _fd_write(fd, iov, iovcnt, pnum) {
    // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0
    var num = 0;
    for (var i = 0; i < iovcnt; i++) {
      var ptr = HEAPU32[((iov)>>2)];
      var len = HEAPU32[(((iov)+(4))>>2)];
      iov += 8;
      for (var j = 0; j < len; j++) {
        printChar(fd, HEAPU8[ptr+j]);
      }
      num += len;
    }
    HEAPU32[((pnum)>>2)] = num;
    return 0;
  }


var wasmImports = {
  "emscripten_memcpy_big": _emscripten_memcpy_big,
  "fd_write": _fd_write
};
var info = {
    'env': wasmImports,
    'wasi_snapshot_preview1': wasmImports,
  };

    const module = await WebAssembly.instantiateStreaming(
      fetch('/test.wasm'),
      info
      ).then(res=>{
        console.log(res)
        // console.log(res.instance.exports.int_sqrt(33)) 可以调用
        // res.instance.exports.main() // 不知道为什么main 函数调用不了
      })
    
})
</script>

<template>

</template>

Emscripten胶水代码初探

 // 别人代码给的一点启发 https://blog.csdn.net/wopelo/article/details/121597551
  // const importObject = {
  //       env: {
  //           // 需要提供一个中止函数,如果断言失败就会调用这个中止函数
  //           abort(_msg, _file, line, column) {
  //               console.error('abort called at index.ts:' + line + ':' + column)
  //           }
  //       },
  //       wasi_snapshot_preview1: wasmImports
  //   }
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在项目安装ffmpeg.wasm和@ffmpeg/ffmpeg,你可以按照以下步骤进行操作: 1. 首先,使用命令`yarn add @ffmpeg/ffmpeg @ffmpeg/core`来将ffmpeg.wasm和@ffmpeg/ffmpeg安装到你的项目。 2. 接下来,你需要创建一个ffmpeg实例。你可以使用`import FFmpeg from 'ffmpeg/@ffmpeg/dist/ffmpeg.min.js'`来导入ffmpeg的核心文件。然后,使用`FFmpeg.createFFmpeg()`方法来创建一个ffmpeg实例,并传入一些配置参数,例如核心文件的路径和日志选项。 3. 然后,你需要等待ffmpeg加载完成。可以使用`await ffmpeg.load()`来等待加载完成。这个过程可能需要一些时间,所以确保在等待期间不会执行其他操作。 综上所述,你可以按照上述步骤在项目安装ffmpeg.wasm和@ffmpeg/ffmpeg。希望对你有所帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [ffmpeg.wasm的使用教程](https://blog.csdn.net/qq_41535611/article/details/121907623)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [ffmpeg.wasm:用于Web浏览器和节点的FFmpeg,由WebAssembly支持](https://download.csdn.net/download/weixin_42125867/18577288)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值