c语言片段
新建文件名为side_module.c
的文件
int Increment(int value) {
return value + 1;
}
int Decrement(int value) {
return value - 1;
}
O1编译
命令
emcc side_module.c -s SIDE_MODULE=2 -O1 -s EXPORTED_FUNCTIONS='["_Increment", "_Decrement"]' -o build/side_module.wasm
SIDE_MODULE=2
标记会告诉Emscripten不想在生成的模块中包含像C标准库这样的东西,也不想生成JavaScript plumbing文件。
新建html导入
将编译好的wasm
文件通过js
加载,内容如下:
(module
(global $env.__memory_base (;0;) (import "env" "__memory_base") i32)
(global $env.__table_base (;1;) (import "env" "__table_base") i32)
(memory $env.memory (;0;) (import "env" "memory") 0)
(func $__wasm_call_ctors (;0;) (export "__wasm_call_ctors")
)
(func $__wasm_apply_data_relocs (;1;) (export "__wasm_apply_data_relocs")
)
(func $Increment (;2;) (export "Increment") (param $var0 i32) (result i32)
local.get $var0
i32.const 1
i32.add
)
(func $Decrement (;3;) (export "Decrement") (param $var0 i32) (result i32)
local.get $var0
i32.const -1
i32.add
)
)
此时js
要正常加载,需要配置全局变量和内存,完整代码:
<script>
let memoryBase = new WebAssembly.Global({value: 'i32'}, 1024);
let tableBase = new WebAssembly.Global({value: 'i32'}, 1024);
let memory = new WebAssembly.Memory({initial: 256, maximum: 256});
const importObject = {
env: {
memory: memory,
__memory_base: memoryBase,
__table_base: tableBase,
}
};
WebAssembly.instantiateStreaming(fetch('side_module.wasm'), importObject).then(result => {
console.log(result.instance.exports);
const value = result.instance.exports.Increment(17);
console.log(value);
})
</script>
O2或O3编译
wasm
内容与上面有些不同:
(module
(func $__wasm_call_ctors (;0;) (export "__wasm_call_ctors") (export "__wasm_apply_data_relocs")
nop
)
(func $Increment (;1;) (export "Increment") (param $var0 i32) (result i32)
local.get $var0
i32.const 1
i32.add
)
(func $Decrement (;2;) (export "Decrement") (param $var0 i32) (result i32)
local.get $var0
i32.const 1
i32.sub
)
)
此时不用定义全局变量和内存就可以正常调用:
<script>
WebAssembly.instantiateStreaming(fetch('side_module.wasm')).then(result => {
console.log(result.instance.exports);
const value = result.instance.exports.Increment(17);
console.log(value);
})
</script>
总结
选项O2
比O1
优化更多内容,O1
选择需要额外定义env
配置来适配模块的全局变量和内存。模块文件分前导、已知段和自定义段,其中Table
段定义函数引用数组,Memory
段定义模块线性内存,相当于堆内存,Global
定义全局变量。
程序运行时,操作系统会先分配内存给全局变量和函数使用,由于wasm
运行在js
虚拟机不能直接申请内存,只能在实例化模块时预先申请ArrayBuffer
充当内存使用。
在学习阶段可以多次编译,查看wasm
内容或程序的需要来决定是否需要设置env
。