我正在尝试使用 webassembly,并且我制作了一个玩具模块,可以在 C 中蛮力素数
extern "C" {
bool isPrime(int n) {
for (int i = 2; i <= n; i++) {
if (n % i == 0) return false;
}
return true;
}
int getPrimes() {
int primesFound = 0;
for (int i = 2; i < 4206969; i++) {
if (isPrime(i)) {
primesFound++;
}
}
return primesFound;
}
}
在 Windows 中用 emcc /O3 编译它会得到以下字节流:
0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0, 0x1, 0x8, 0x2, 0x60,
0x0, 0x0, 0x60, 0x0, 0x1, 0x7f, 0x3, 0x3, 0x2, 0x0, 0x1, 0x5, 0x6, 0x1, 0x1, 0x80, 0x2,
0x80, 0x2, 0x7, 0x1f, 0x3, 0x6, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x2, 0x0, 0x9, 0x67,
0x65, 0x74, 0x50, 0x72, 0x69, 0x6d, 0x65, 0x73, 0x0, 0x1, 0x6, 0x5f, 0x73, 0x74, 0x61,
0x72, 0x74, 0x0, 0x0, 0xa, 0x4e, 0x2, 0x3, 0x0, 0x1, 0xb, 0x48, 0x1, 0x4, 0x7f, 0x41,
0x2, 0x21, 0x0, 0x3, 0x40, 0x41, 0x2, 0x21, 0x1, 0x2, 0x40, 0x3, 0x40, 0x20, 0x0, 0x20,
0x1, 0x70, 0x45, 0xd, 0x1, 0x20, 0x0, 0x20, 0x1, 0x46, 0x21, 0x3, 0x20, 0x1, 0x41, 0x1,
0x6a, 0x21, 0x1, 0x20, 0x3, 0x45, 0xd, 0x0, 0xb, 0x20, 0x2, 0x41, 0x1, 0x6a, 0x21, 0x2,
0xb, 0x20, 0x0, 0x41, 0x1, 0x6a, 0x22, 0x0, 0x41, 0xf9, 0xe2, 0x80, 0x2, 0x47, 0xd, 0x0,
0xb, 0x20, 0x2, 0xb, 0xb, 0xa, 0x1, 0x0, 0x41, 0x80, 0xc, 0xb, 0x3, 0xa0, 0x6, 0x50
大多数人可能难以理解,但 VSC 的 WASM 到 WAT 工具表明这代表以下 WASM:
(module
(type $t0 (func))
(type $t1 (func (result i32)))
(func $_start (type $t0)
nop)
(func $getPrimes (type $t1) (result i32)
(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32)
i32.const 2
local.set $l0
loop $L0
i32.const 2
local.set $l1
block $B1
loop $L2
local.get $l0
local.get $l1
i32.rem_u
i32.eqz
br_if $B1
local.get $l0
local.get $l1
i32.eq
local.set $l3
local.get $l1
i32.const 1
i32.add
local.set $l1
local.get $l3
i32.eqz
br_if $L2
end
local.get $l2
i32.const 1
i32.add
local.set $l2
end
local.get $l0
i32.const 1
i32.add
local.tee $l0
i32.const 4206969
i32.ne
br_if $L0
end
local.get $l2)
(memory $memory 256 256)
(export "memory" (memory 0))
(export "getPrimes" (func $getPrimes))
(export "_start" (func $_start))
(data $d0 (i32.const 1536) "\a0\06P"))
从另一个程序调用以下 EM_JS,其意图是来自 WASM,它告诉 javascript 引擎编译一些 WASM,然后执行它。
EM_JS(int, call_wasmBlock, (const uint8_t* wasmBlock, uint32_t length), {
let wasmBuf = new Uint8Array(Module.HEAPU8.buffer, wasmBlock, length);
WebAssembly.instantiate(wasmBuf)
.then(
obj => console.log(obj.instance.exports.getPrimes())
);
});
我收到此错误:
Uncaught (in promise) CompileError: WebAssembly.instantiate(): unexpected section <Export> @+158
我不完全确定该去哪里,这主要是对 webassembly 的限制进行试验。