在Windows10搭建WebAssembly開發環境


最近研究WebAssembly技術,准備用WebAssembly編譯C/C++代碼供前端調用。網上看了很多文章,收獲很大,現在就遇到的問題做一個記錄。

官網關於windows開發環境搭建基本上幾句話,寫的太簡單,看來是把每個人都當資深程序員了。

https://emscripten.org/docs/getting_started/downloads.html

 

初學者估計會看的一臉懵。網上找了很多文章,都沒有特別詳細的操作步驟。由於命令行用的不熟,再加上有些文章說用命令安裝,數據源來自谷歌,如果沒有代理的話可能會下載失敗。因此我一開始沒有使用官方推薦的方法,而是找了一篇文章,下載了文章中附件emsdk-1.35.0-full-64bit.exe的安裝包,安裝后點擊emsdk_env.bat會自動配置環境變量,永久生效。編寫的一個Hello world的C文件也成功編譯成了如下圖所列的文件:

emcc hello.c -s WASM=1 -o hello.html

 

 

 

 這個安裝版的emsdk可以在任意目錄先打開cmd執行編譯,因為它已經配置了永久生效的系統環境變量。

 直接雙擊打開hello.html,能正常顯示:

 

 

由於我的目標是編譯C/C++生成wasm文件,再引入到前端,供js調用C/C++里面的方法,因此當我再編譯一個包含自定義加法和乘法的math.c的C文件在前端調用時,代碼一直報錯找不到這個wasm文件,我確認引入wasm文件路徑沒有問題,因為反復嘗試了十幾遍,都是報錯404找不到這個math.wasm。此時我就開始懷疑安裝的這個emsdk有問題。

因為官網上最新版本編譯hello.c文件生成是這樣的:

 

 和我自己生成的明顯不一樣:

因此我下定決心,把剛安裝的emsdk1.35.0卸載了,重新按照官網的步驟安裝最新版試試。

由於我第一次用安裝文件安裝時,它會默認安裝在C盤,因此環境變量是自動配置C盤路徑,卸載時環境變量一起被自動清除了。

1、依據官網步驟,首先安裝Git(我很早已經安裝了),略過。

2、安裝windows CMake

3、安裝python

4、在電腦的其他盤,我的在D盤,創建一個目錄D:\devEnv\webAssembly。

5、在webAssembly目錄下cmd窗口執行下面命令:

 

 

     git clone https://github.com/juj/emsdk.git

     這個從github上下載很快,1分鍾搞定。

6、進入下載好的emsdk目錄,繼續cmd安裝最新版本(這一步就是從谷歌的一個地址下載文件,我嘗試了很多遍,一開始執行emsdk install  latest報無法連接服務器,1060等錯誤,試了半天都不行,最后用下面這行命令終於成功了)

emsdk install --global latest

7、當安裝完成配置好后執行激活:

emsdk activate latest


8、配置激活后需要應用環境變量(該步操作在每次打開新的cmd窗口時都需要執行emsdk_env.bat,相當於臨時配置。手動永久配置到系統的環境變量里我還沒嘗試)

emsdk_env.bat


9、驗證是否安裝成功

emcc -v 不會報錯
emcc --clear-cache 不會報錯


注意:由於我沒有手動配置系統環境變量,以上命令操作只能在D:\devEnv\webAssembly\emsdk下執行,其他任何地方執行都會報命令找不到,而且編譯C/C++文件也要在這個目錄下編譯,因為D:\devEnv\webAssembly\emsdk就是編譯環境。

 

 

 

 

至此安裝完成。可以再嘗試編譯hello.c生成的文件如下,和官網一致。此時不能直接雙擊打開了,需要一個本地服務器來訪問hello.html。

繼續編譯math.c,生成math.wasm。在前端調用math.wasm中的加法和乘法。

 

 

安裝http服務器 npm install -g serve

cmd啟動http服務命令: serve .

瀏覽器訪問自己寫的工程目錄index.html

 

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>
<div id="devTarget" />
</h1>
<script>
/**
* @param {String} path wasm 文件路徑
* @param {Object} imports 傳遞到 wasm 代碼中的變量
*/
function loadWebAssembly (path, imports = {}) {
return fetch(path)
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.compile(buffer))
.then(module => {
imports.env = imports.env || {};

// 開辟內存空間
imports.env.memoryBase = imports.env.memoryBase || 0;
if (!imports.env.memory) {
imports.env.memory = new WebAssembly.Memory({ initial: 256 });
}

// 創建變量映射表
imports.env.tableBase = imports.env.tableBase || 0;
if (!imports.env.table) {
// 在 MVP 版本中 element 只能是 "anyfunc"
imports.env.table = new WebAssembly.Table({ initial: 0, element: 'anyfunc' });
}

// 創建 WebAssembly 實例
return new WebAssembly.Instance(module, imports);
})
}
//調用
loadWebAssembly('./math.wasm')
.then(instance => {
const add = instance.exports.add; //取出c里面的方法
const square = instance.exports.square; //取出c里面的方法
let span = document.createElement('span');
let htmlStr = '10 + 20 = ' + add(10, 20);
htmlStr += '; 3 * 3 = ' + square(3);
span.innerHTML = htmlStr;
let div = document.getElementById('devTarget');
div.appendChild(span);

console.log('10 + 20 =', add(10, 20));
console.log('3*3 =', square(3));
console.log('(2 + 5)*2 =', square(add(2 + 5)));
})

</script>
</body>
</html>

其中index.html中調用math.wasm中的加法和乘法,在頁面顯示出

 

 

http://localhost:5000/Desktop/math/

 

 參考文章鏈接:

https://www.cnblogs.com/jixiaohua/p/10424941.html

https://blog.csdn.net/wangx893175022/article/details/106209322/

 


免責聲明!

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



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