Blog Entry
在React中使用Wasm
在React中使用Wasm
- Created
- 2022/02/07
- Updated
- 2022/02/07
wasm版本
webpack已经有了几个关于WebAssembly的试验特性,支持直接导入wasm文件,这里试验一下看.
直接运行试验项目,或者一步步来
- 使用Create React App新建项目:
# 在 xkexp.cpp/wasm 目录npx create-react-app in-reactcd in-reactyarnyarn add -D react-app-rewired- 建立配置文件
config-overrides.js(用于覆盖CRA配置)
/* config-overrides.js */
module.exports = { webpack: function(config, env) {
config.experiments.asyncWebAssembly = true; config.experiments.syncWebAssembly = true;
return config; }}- 修改脚本
"scripts": {- "start": "react-scripts start",+ "start": "react-app-rewired start",- "build": "react-scripts build",+ "build": "react-app-rewired build",- "test": "react-scripts test",+ "test": "react-app-rewired test", "eject": "react-scripts eject"}- 运行
yarn# 调用build-function.ps1脚本,将noprint.c生成xkfunc.wasmyarn build:wasm# 启动开发服务yarn startmjs版本
运行试验项目
yarn# 调用build-function-mjs.ps1脚本,将main.c生成xkfunc.mjsyarn build:mjs# 启动开发服务# 启动成功后,控制台应该有调用xkFunc的输出了yarn start核心代码
src/App.js
import React, { useEffect } from 'react';import logo from './logo.svg';import './App.css';// 导入mjsimport xkFuncModule from './xkfunc.mjs';
function App() {
// 在useEffect中调用c函数 useEffect(() => { xkFuncModule() .then(Module => { Module.ccall("xkFunc", null, null, null); }) });
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;目录及文件
└─ root 基础目录 ├─ function c目录 │ ├─ main.c c文件 │ └─ noprint.c c文件(无打印) ├─ in-react wasm版本 └─ in-react-mjs mjs版本 └─ scripts 脚本目录 └─ build-function-mjs.ps1 c转mjs脚本main.c
文件: function/main.c
#include <stdio.h>
int main(int argc, char** argv) { printf("Hello World!\n"); printf("Hello Function!\n"); return 0;}
int xkFunc(int argc, char** argv) { printf("xkFunc be called! return 100\n"); return 100;}noprintf.C
文件: function/noprintf.c
#include <stdio.h>
int main(int argc, char** argv) { return 0;}
int xkFunc(int argc, char** argv) { return 100;}build-function-mjs.ps1
文件: in-react-mjs/scripts/build-function-mjs.ps1
# 如果没有输出,或者其他诡异错误,试着删除所有中文注释
# 设置emsdk环境变量&"$Env:EMSDK/emsdk.ps1" construct_env
# 编译# 输出为src/xkfunc.mjs,没有报错就是成功Write-Host "emcc compile start"emcc --no-entry ../function/main.c -o src/xkfunc.mjs ` -s ENVIRONMENT='web' ` -s SINGLE_FILE=1 ` -s EXPORT_NAME='xkFuncModule' ` -s USE_ES6_IMPORT_META=0 ` -s EXPORTED_FUNCTIONS='["_main", "_xkFunc"]' ` -s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' ` -O3Write-Host "emcc compile end"坑
Module not found: Error: Can’t resolve ‘wasi_snapshot_preview1’
emscripten使用了wasi_snapshot_preview1.fd_write用于输出,比如C里面的printf打印的结果,可以通过wasm输出到浏览器的控制台.
前面参考项目中的function/main.c中多次使用printf,导致一直报这个错误.
改用function/noprint.c不用输出,则可以正常在React中编译运行了