emcc命令使用范例,cpp编译成wasm在html中使用
发布于 作者:苏南大叔 来源:程序如此灵动~

Emscripten
是WebAssembly
的编译器,它可以将C/C++
代码编译成WebAssembly
,然后通过JavaScript
调用。emcc
命令就是其中最常用的的命令。本文以一个demo.cpp
作为引子,演示emcc
编译命令的主要功能。
苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。测试环境:win10
,emcc@4.0.4
。
emcc 命令安装
本文的正确使用前提,是已经安装好了Emscripten
。参考文章:
可以在命令行下面,试试执行下面的命令。如果有输出,则证明环境安装正确。
emcc --version
测试:注意事项
本文生成结果的测试,需要使用html
文件调用wasm
文件,所以存在着跨域的问题。双击html
文件打开浏览器,会报错。所以,请自行准备容器运行测试。比如nginx
/apache
等。或者简单的使用php
或python
(推荐)或node
或rust
,启动一个自带容器。
推荐的容器方案,最简单的方案是python
。其它传统的方案,都需要做设置,或写代码,或修改mime
映射,略显复杂。容器启动命令:
python -m http.server 8080
起源:demo.cpp
demo.cpp
文件,提供了三个导出函数,分别是:add()
、greeting()
、greeting_alert()
。代码如下:
#include <emscripten.h>
#include <string>
extern "C" {
EMSCRIPTEN_KEEPALIVE
int add(int a, int b) {
return a + b;
}
EMSCRIPTEN_KEEPALIVE
const char* greeting() {
return "Hello from WebAssembly!";
}
EMSCRIPTEN_KEEPALIVE
void greeting_alert() {
emscripten_run_script("alert('欢迎使用 WebAssembly!')");
}
}
剩下的js
文件和.wasm
文件,以及调用的demo.html
文件,都是通过emcc
命令对这个cpp
文件进行处理而得到的。
编译项目
emcc
命令,
- 如果
-o
是个html
文件的话,则会生成wasm
、js
和html
文件。 - 如果
-o
是个js
文件的话,则会生成wasm
、js
文件。
官方推荐命令
生成HTML测试模板,官方推荐的命令是这样的:
emcc demo.cpp -o index.html
然而,通过官方命令生成的index.html
,代码太复杂了,不符合快速测试的要求。中间还放了个大大的啥用也没有的canvas
,可能它的需求设计里面,都是编译游戏到wasm
的吧。其实,苏南大叔这边的测试目的,仅仅是为了隐藏一些js
函数的逻辑,起到加密的目的。
可以输出全局变量Module
来查看可以使用的函数。
本文范例编译
下面的命令和模版,都是vscode
自带的copilot
推荐的。
emcc demo.cpp -o demo.js -s EXPORTED_FUNCTIONS="['_add', '_greeting','_greeting_alert']" -s EXPORTED_RUNTIME_METHODS="['UTF8ToString']"
配套html
:
<button onclick="callAdd()">Add</button>
<button onclick="callGreeting()">Greeting</button>
<button onclick="callGreetingAlert()">Greeting Alert</button>
<script src="demo.js"></script>
<script>
function callAdd() {
var result = Module._add(5, 3);
console.log("Result of add: " + result);
}
function callGreeting() {
var greeting = Module.UTF8ToString(Module._greeting());
console.log(greeting);
}
function callGreetingAlert() {
Module._greeting_alert();
}
</script>
可能存在的问题
这里提一个在测试wasm
的可能比较常见的问题,就是函数返回输出字符串的问题。在好几个不同的测试环境下,wasm
该输出的字符串,都变成了数字,很奇怪吧?
比如,使用下面的命令输出的demo.js
文件:
emcc -Oz --closure 1 -s ENVIRONMENT=web -s FILESYSTEM=0 demo.cpp -o demo.js
所以,是编译命令的参数问题,注意调试修改。
结语
本文主要以介绍emcc
命令的使用方式为主,通过一个cpp
文件衍生出对应的js
和wasm
文件,并成功通过html
文件进行调用。
更多苏南大叔的wasm
文件相关经验文章,请参考:


