如何在 vue.js 中调用 WebAssembly 方法?

2023-12-27

我正在尝试将这个简单的 html 页面 add.html 转置到 vue.js:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
  </head>
  <body>
    <input type="button" value="Add" onclick="callAdd()" />

    <script>
      function callAdd() {
        const result = Module.ccall('Add',
            'number',
            ['number', 'number'],
            [1, 2]);

        console.log(`Result: ${result}`);
      }
    </script>
    <script src="js_plumbing.js"></script>
  </body>
</html>

它调用 add.c 中定义的 Add 函数:

#include <stdlib.h>
#include <emscripten.h>

// If this is an Emscripten (WebAssembly) build then...
#ifdef __EMSCRIPTEN__
  #include <emscripten.h>
#endif

#ifdef __cplusplus
extern "C" { // So that the C++ compiler does not rename our function names
#endif

EMSCRIPTEN_KEEPALIVE
int Add(int value1, int value2) 
{
  return (value1 + value2); 
}

#ifdef __cplusplus
}
#endif

并通过命令转换为js_plumbing和js_plumbling.wasm文件:

emcc add.c -o js_plumbing.js -s EXTRA_EXPORTED_RUNTIME_METHODS=['ccall','cwrap'] -s 
ENVIRONMENT='web','worker'

在谷歌浏览器的控制台中我收到以下错误:

GET http://localhost:8080/dist/js_plumbing.wasm 404 (Not Found)  @  js_plumbing.js?2b2c:1653

js_plumbing_js 中的位置:

// Prefer streaming instantiation if available.
  function instantiateAsync() {
    if (!wasmBinary &&
        typeof WebAssembly.instantiateStreaming === 'function' &&
        !isDataURI(wasmBinaryFile) &&
        typeof fetch === 'function') {
      fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function (response) {  // <---------------!!!
        var result = WebAssembly.instantiateStreaming(response, info);
        return result.then(receiveInstantiatedSource, function(reason) {
            // We expect the most common failure cause to be a bad MIME type for the binary,
            // in which case falling back to ArrayBuffer instantiation should work.
            err('wasm streaming compile failed: ' + reason);
            err('falling back to ArrayBuffer instantiation');
            instantiateArrayBuffer(receiveInstantiatedSource);
          });
      });
    } else {
      return instantiateArrayBuffer(receiveInstantiatedSource);
    }
  }

在 Google Chrome 中:createWasm @ js_plumbing.js?2b2c:1680

js_plumbing.js 第 1680 行:

instantiateAsync();

在 Google Chrome 中: eval @ js_plumbing.js?2b2c:1930

js_plumbing.js 第 1930 行:

<pre><font color="#4E9A06">var</font> asm = createWasm();</pre>

还有许多与 wasm 相关的其他错误:

那么...我应该如何修改 Result.vue 中的 callAdd() 方法才能正确执行 js_plumbing.js 和 js_plumbing.wasm 文件中的 Add 函数?

  methods: {
    callAdd() {
      const result = Module.ccall('Add',
          'number',
          ['number', 'number'],
          [1, 2]);
      console.log('Result: ${result}');
    }
  }

Updates:

1 次更新)

我用以下命令编译了 add.c:

emcc add.c -o js_plumbing.mjs -s EXTRA_EXPORTED_RUNTIME_METHODS=
['ccall','cwrap'] -s ENVIRONMENT='web' . 

然后创建一个 js_plumbing.js 文件:

. import wasm from './js_plumbing.mjs';

const instance = wasm({
  onRuntimeInitialized() {
    console.log(instance._addTwoNumbers(3,2));
  }
}) . 

执行 npm run dev:

Failed to compile.

./src/components/js_plumbing.mjs 3:25
Module parse failed: Unexpected token (3:25)
You may need an appropriate loader to handle this file type, currently 
no loaders are configured to process this file. 
See https://webpack.js.org/concepts#loaders
| 
| var Module = (function() {
>   var _scriptDir = import.meta.url;
|   
|   return (

更新2)

我通过将 wasm 文件放入 index.html 文件同一文件夹内的 /div 子文件夹中解决了 404 错误。

Now I’m facing this problem: “Cannot read property ‘ccall’ of undefined” enter image description here

但我使用此命令编译了 add.c 文件,创建了 js_plumbing.js 和 js_plumbing.wasm 文件,该命令导出了方法 ‘ccall’ 和 ‘cwrap’ :

emcc add.c -o js_plumbing.js -s EXTRA_EXPORTED_RUNTIME_METHODS=[‘ccall’,‘cwrap’] -s ENVIRONMENT=‘web’,‘worker’

3°更新)

我通过某种黑客手段“解决”了这个问题,但我根本不喜欢这种方式。

这是 Result.vue 文件:

<template>
  <div>
    <p button @click="callAdd">Add!</p>
    <p>Result: {{ result }}</p>
  </div>
</template>

<script>
    import * as js_plumbing from './js_plumbing'
    import Module  from './js_plumbing'
    export default {
      data () {
        return {
          result: null
        }
      },
      methods: {
        callAdd () {
          const result = js_plumbing.Module.ccall('Add',
            'number',
            ['number', 'number'],
            [1, 2]);
          this.result = result;
        }
      }
    }
</script>

和之前用的一模一样

为了使其正常工作,我所做的唯一一件事是将导出添加到 js_plumbing.js 中的模块定义中:

js_plumbing.js

// Copyright 2010 The Emscripten Authors.  All rights reserved.
// Emscripten is available under two separate licenses, the MIT 
license and the
// University of Illinois/NCSA Open Source License.  Both these 
licenses can be
// found in the LICENSE file.

// The Module object: Our interface to the outside world. We import
// and export values on it. There are various ways Module can be used:
// 1. Not defined. We create it here
// 2. A function parameter, function(Module) { ..generated code.. }
// 3. pre-run appended it, var Module = {}; ..generated code..
// 4. External script tag defines var Module.
// We need to check if Module already exists (e.g. case 3 above).
// Substitution will be replaced with actual code on later stage of 
the build,
// this way Closure Compiler will not mangle it (e.g. case 4. above).
// Note that if you want to run closure, and also to use Module
// after the generated code, you will need to define   var Module = 
{};
// before the code. Then that object will be used in the code, and you
// can continue to use Module afterwards as well.
export var Module = typeof Module !== 'undefined' ? Module : {};

但是,正如我所说,我不喜欢这种黑客行为。 关于如何使模块可导出、从而可导入,而不需要在 js_plumbing.js 文件中手动添加“导出”,有什么建议吗?


首先,应该解决 404 错误。是否归档/dist/js_plumbing.wasm存在?我过去需要手动复制 .wasm 文件,因为某些自动构建系统(如 Parcel)目前不需要。

您可以使用MODULARIZE导入到构建系统的选项。

addTwoNumbers.c

#include <emscripten.h>

EMSCRIPTEN_KEEPALIVE
int addTwoNumbers(int value1, int value2) 
{
  return (value1 + value2); 
}

构建命令

$ emcc -o dist/addTwoNumbers.js -s MODULARIZE=1 src/addTwoNumbers.c

Vue 实现

import myMathModule from './js_plumbing';

let instance = {
  ready: new Promise(resolve => {
    myMathModule({
      onRuntimeInitialized() {
        instance = Object.assign(this, {
          ready: Promise.resolve()
        });
        resolve();
      }
    });
  })
};

export default {
  data () {
    return {
      result: null
    };
  },
  methods: {
    callAdd(a, b) {
      instance.ready
      .then(_ => this.result = instance._add(a, b));
    }
  }
};

Use the onRuntimeInitialized检测 WASM 模块何时准备就绪的方法。您导出的函数前面会有一个下划线。

require()可能可以用来代替import:

const wasmModule = require('./addTwoNumbers.js');

...
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 vue.js 中调用 WebAssembly 方法? 的相关文章

  • backbone.js:视图中影响集合中不同模型的按钮

    我刚刚开始使用backbone js 到目前为止 我真的很喜欢它 我有这样的事情 ModelA ModelB ViewA ViewB ModelA 持有 ModelB 的集合 如何使用按钮构建模型 B 的视图 单击该按钮会更改集合中下一个
  • 如何修复带有单个道具的括号的 prettier 和 tslint 错误?

    我使用 prettier 和 tslint https github com alexjoverm tslint config prettier https github com alexjoverm tslint config prett
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • 为什么模板不能位于外部“C”块内?

    这是一个后续问题一个答案 https stackoverflow com questions 4866433 is it possible to typedef a pointer to extern c function type wit
  • 如何使用 HTML5 Javascript Canvas 获取三个碰撞形状的交集并删除不碰撞的部分?

    我最近专门针对 KonvaJs 发布了类似的问题here https stackoverflow com questions 64603077 how can i get the intersection of three shapes c
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 我的 strlcpy 版本

    海湾合作委员会 4 4 4 c89 我的程序做了很多字符串处理 我不想使用 strncpy 因为它不会终止 我不能使用 strlcpy 因为它不可移植 只是几个问题 我怎样才能让我的函数正常运行 以确保它完全安全稳定 单元测试 这对于生产来
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 更改窗口的内容 (WPF)

    我创建了一个简单的 WPF 应用程序 它有两个 Windows 用户在第一个窗口中填写一些信息 然后单击 确定 这会将他们带到第二个窗口 这工作正常 但我试图将两个窗口合并到一个窗口中 这样只是内容发生了变化 我设法找到了这个更改窗口内容时
  • 如何在 JSP 编辑器中激活 javascript 的语法着色 - Eclipse

    在某些情况下 javascript 确实必须位于 JSP 页面中 而不是位于单独的文件中 有些框架还使用Javascript做一些事情 以便用户将其包含到JSP标签中 这样JS就不会出现在
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • 在 Javascript 中创建数组

    我对 javascript 不太熟悉 并且在用 javascript 制作 2d 或者也许我可能需要 3d 数组时遇到了一些麻烦 我目前需要收集 2 条信息 一个 ID 和一个值 因此我创建了以下内容 var myArray var id
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • 开玩笑 setTimeout 不暂停测试

    it has working hooks async gt setTimeout gt console log Why don t I run expect true toBe true 15000 我已经查看了这个答案 Jest 文档和几
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co

随机推荐