首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Webassembly -尝试编译代码缓冲区并通过C++通过EM_JS执行它

Webassembly -尝试编译代码缓冲区并通过C++通过EM_JS执行它
EN

Stack Overflow用户
提问于 2020-03-19 06:27:12
回答 1查看 250关注 0票数 1

我正在试验webassembly,并且我已经制作了一个玩具模块,它可以用C++暴力强制素数

代码语言:javascript
运行
复制
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编译得到以下字节流:

代码语言:javascript
运行
复制
    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 to WAT工具表明,这代表了以下WASM:

代码语言:javascript
运行
复制
(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,然后执行它。

代码语言:javascript
运行
复制
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())
        );
});

我得到了这个错误:

代码语言:javascript
运行
复制
Uncaught (in promise) CompileError: WebAssembly.instantiate(): unexpected section <Export> @+158

我不完全确定该怎么做,这主要是在试验webassembly的局限性。

EN

回答 1

Stack Overflow用户

发布于 2020-04-27 06:36:45

index.js

代码语言:javascript
运行
复制
'use strict';

import fs from 'fs';

const bin = fs.readFileSync('test.wasm');

// only checks for primes up to 100
const primeAppBin = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 10, 2, 96, 0, 1, 127, 96, 1, 127, 1, 127, 3, 3, 2, 1, 0, 5, 4, 1, 1, 1, 1, 7, 32, 3, 6, 109, 101, 109, 111, 114, 121, 2, 0, 7, 105, 115, 80, 114, 105, 109, 101, 0, 0, 9, 103, 101, 116, 80, 114, 105, 109, 101, 115, 0, 1, 10, 142, 1, 2, 61, 1, 2, 127, 65, 1, 33, 1, 32, 0, 65, 4, 78, 4, 127, 32, 0, 65, 127, 106, 33, 2, 65, 2, 33, 1, 2, 64, 3, 64, 32, 0, 32, 1, 111, 69, 13, 1, 32, 1, 65, 1, 106, 34, 1, 32, 2, 71, 13, 0, 11, 65, 1, 15, 11, 65, 0, 5, 65, 1, 11, 11, 78, 1, 4, 127, 65, 2, 33, 0, 3, 64, 2, 64, 32, 0, 65, 4, 79, 4, 64, 32, 0, 65, 127, 106, 33, 3, 65, 2, 33, 2, 3, 64, 32, 0, 32, 2, 112, 69, 13, 2, 32, 2, 65, 1, 106, 34, 2, 32, 3, 71, 13, 0, 11, 11, 32, 1, 65, 1, 106, 33, 1, 11, 32, 0, 65, 1, 106, 34, 0, 65, 228, 0, 71, 13, 0, 11, 32, 1, 11, 11, 9, 1, 0, 65, 128, 12, 11, 2, 160, 6]);

(async () => {
  let buff;
  const imports = {
    env: {
      execWasm: (byteOffset, length) => {
        WebAssembly.instantiate(new Uint8Array(buff, byteOffset, length)).then(app => console.log(app.instance.exports.getPrimes() + ' primes found'));
      }
    }
  };
  const app = await WebAssembly.instantiate(bin, imports);
  const { memory, test } = app.instance.exports;
  const view = new Uint8Array(memory.buffer, 0, primeAppBin.length);
  for (let i in view) view[i] = primeAppBin[i];
  buff = memory.buffer;
  test(view.byteOffset, view.byteLength);
})();

test.cpp

代码语言:javascript
运行
复制
// emcc -O3 "test.cpp" -o "test.wasm" -s STANDALONE_WASM -s EXPORTED_FUNCTIONS="['_test']" -s ERROR_ON_UNDEFINED_SYMBOLS=0 -Wl,--no-entry -msimd128 -s INITIAL_MEMORY=64kb -s ALLOW_MEMORY_GROWTH=0 -s TOTAL_STACK=0kb

#include <emscripten.h>

extern "C" {
  extern void execWasm(int byteOffset, int length);
  EMSCRIPTEN_KEEPALIVE
  void test (int byteOffset, int length) {
    execWasm(byteOffset, length);
  }
}

primes.cpp

代码语言:javascript
运行
复制
// emcc -O3 "primes.cpp" -o "primes.wasm" -s STANDALONE_WASM -s EXPORTED_FUNCTIONS="['_getPrimes']" -s ERROR_ON_UNDEFINED_SYMBOLS=0 -Wl,--no-entry -msimd128 -s INITIAL_MEMORY=64kb -s ALLOW_MEMORY_GROWTH=0 -s TOTAL_STACK=0kb

extern "C" {
    bool isPrime(int n) {
        for (int i = 2; i < n - 1; i++) {
            if (n % i == 0)
            return false;
        }
    return true;
    }

    int getPrimes() {
        int primesFound = 0;

        for (int i = 2; i < 4'206'969; i++) {
            if (isPrime(i)) {
                primesFound++;
            }
        }
        return primesFound;
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60748355

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档