我们相信:世界是美好的,你是我也是。 来玩一下解压小游戏吧!

EmscriptenWebAssembly的编译器,它可以将C/C++代码编译成WebAssembly,然后通过JavaScript调用。emcc命令就是其中最常用的的命令。本文以一个demo.cpp作为引子,演示emcc编译命令的主要功能。

苏南大叔:emcc命令使用范例,cpp编译成wasm在html中使用 - emcc-wasm
emcc命令使用范例,cpp编译成wasm在html中使用(图6-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。测试环境:win10emcc@4.0.4

emcc 命令安装

本文的正确使用前提,是已经安装好了Emscripten。参考文章:

可以在命令行下面,试试执行下面的命令。如果有输出,则证明环境安装正确。

emcc --version

苏南大叔:emcc命令使用范例,cpp编译成wasm在html中使用 - emcc-version
emcc命令使用范例,cpp编译成wasm在html中使用(图6-2)

测试:注意事项

本文生成结果的测试,需要使用html文件调用wasm文件,所以存在着跨域的问题。双击html文件打开浏览器,会报错。所以,请自行准备容器运行测试。比如nginx/apache等。或者简单的使用phppython(推荐)或noderust,启动一个自带容器。

推荐的容器方案,最简单的方案是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命令使用范例,cpp编译成wasm在html中使用 - 导出函数
emcc命令使用范例,cpp编译成wasm在html中使用(图6-3)

编译项目

emcc命令,

  • 如果-o是个html文件的话,则会生成wasmjshtml文件。
  • 如果-o是个js文件的话,则会生成wasmjs文件。

官方推荐命令

生成HTML测试模板,官方推荐的命令是这样的:

emcc demo.cpp -o index.html

然而,通过官方命令生成的index.html,代码太复杂了,不符合快速测试的要求。中间还放了个大大的啥用也没有的canvas,可能它的需求设计里面,都是编译游戏到wasm的吧。其实,苏南大叔这边的测试目的,仅仅是为了隐藏一些js函数的逻辑,起到加密的目的。

可以输出全局变量Module来查看可以使用的函数。

苏南大叔:emcc命令使用范例,cpp编译成wasm在html中使用 - 默认模版
emcc命令使用范例,cpp编译成wasm在html中使用(图6-4)

本文范例编译

下面的命令和模版,都是vscode自带的copilot推荐的。

emcc demo.cpp -o demo.js -s EXPORTED_FUNCTIONS="['_add', '_greeting','_greeting_alert']" -s EXPORTED_RUNTIME_METHODS="['UTF8ToString']"

苏南大叔:emcc命令使用范例,cpp编译成wasm在html中使用 - 测试界面
emcc命令使用范例,cpp编译成wasm在html中使用(图6-5)

配套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编译成wasm在html中使用 - module-greeting
emcc命令使用范例,cpp编译成wasm在html中使用(图6-6)

所以,是编译命令的参数问题,注意调试修改。

结语

本文主要以介绍emcc命令的使用方式为主,通过一个cpp文件衍生出对应的jswasm文件,并成功通过html文件进行调用。

更多苏南大叔的wasm文件相关经验文章,请参考:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   wasm    emcc