如何在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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM