• 如何在React项目中直接使用WebAssembly


    前言

    自从入坑WebAssembly以来,躺了很多坑,也浏览了很多资料,都没有看到很多能够直接在前端项目中使用WebAssembly的例子。即使有,我自己按照介绍的步骤一步一步来,
    也会报各种错误,官方的文档也写的比较模糊。于是,就决定自己撸一个,让React项目能够直接的借助Webpack,在代码中引入已经编译好的C++模块。

    写一个C语言模块

    int add(int a, int b) {
      return a + b;
    }
    

    使用emscripten对C模块进行编译

    执行以下代码对上面的add.c文件进行编译。

    emcc add.c -Os -s WASM=1 -s SIDE_MODULE=1 -o add.wasm
    

    -Os代码我的模块需要优化,-s WASM=1代表我需要Wasm的第一个版本,-s SIDE_MODULE=1代表我不需要多余的代码,就只要这一个模块。-o add.wasm表示我的输出文件为add.wasm。然后就可以看到在与add.c同级的目录下生成了add.wasm。然后把add.wasm放到public目录下。

    新建一个react项目

    npx create-react-app my-project
    cd my-project
    yarn install
    yarn start
    

    执行完上述的命令,一个简单的react项目就在你本地的3000端口启动了。

    获取webpack控制权

    然后再执行以下命令。

    yarn run eject
    

    运行之后就可以看到webpack的配置文件了。

    安装loader和fetch

    yarn add wasm-loader && yarn add node-fetch
    

    更新webpack配置文件

    找到webpack配置文件,在相应的位置添加如下配置。

    {
        test: /.wasm$/,
        type: 'javascript/auto',
        loaders: ['wasm-loader']
    }
    

    修改App.js文件

    修改App.js。将其替换为如下代码。

    import React, {Component} from 'react';
    import logo from './logo.svg';
    import fetch from 'node-fetch';
    import './App.css';
    
    class App extends Component {
      componentDidMount() {
        this.doSomething();
      }
    
      getExportFunction = async (url) => {
        const env = {
          memoryBase: 0,
          tableBase: 0,
          memory: new WebAssembly.Memory({
            initial: 256
          }),
          table: new WebAssembly.Table({
            initial: 2,
            element: 'anyfunc'
          })
        };
        const instance = await fetch(url).then((response) => {
          return response.arrayBuffer();
        }).then((bytes) => {
          return WebAssembly.instantiate(bytes, {env: env})
        }).then((instance) => {
          return instance.instance.exports;
        });
        return instance;
      };
    
      doSomething = async () => {
        const wasmUrl = 'http://localhost:3000/add.wasm';
        const { add } = await this.getExportFunction(wasmUrl);
        console.log(add(200,2034));
      };
    
      render() {
        return (
          <div className="App">
            <header className="App-header">
              <img src={logo} className="App-logo" alt="logo"/>
              <p>
                Edit <code>src/App.js</code> and save to reload.
              </p>
              <a
                className="App-link"
                href="https://reactjs.org"
                target="_blank"
                rel="noopener noreferrer"
              >
                Learn React
              </a>
            </header>
          </div>
        );
      }
    }
    
    export default App;
    

    可以看到App类中有个函数叫getExportFunction,这个函数接受一个url参数,这个url是远程wasm文件的地址。然后动态的根据传入url,解析其中的编译好的function

    运行

    执行以下命令启动项目。

    yarn start
    

    然后就可以在控制台中看到输出的49,是直接调用的我们用C语言写的add函数。

    举个例子

    完整的项目代码在这里,欢迎Star。

  • 相关阅读:
    python的数据类型+常用操作符
    厉害了
    git merge ignore line ending
    CNAME , DNS , A Record , Domain Name

    setcookie无效
    magic quote gpc htmlspecialchars
    整型 浮点型 不能转化
    git push -f带来的conflict如何解决
    git pull --rebase
  • 原文地址:https://www.cnblogs.com/detectiveHLH/p/9881626.html
Copyright © 2020-2023  润新知