删除“-s ONLY_MY_CODE = 1”编译参数会导致WebAssembly程序中断

时间:2017-11-12 05:15:38

标签: c++ emscripten webassembly

我有一个小的WebAssembly程序,在通过以下bash脚本编译时可以正常工作:

source_list="../../src/cpp/main/main.cc"
emcc -std=c++11 $source_list -o out/index.html -O1 -s WASM=1  -s ONLY_MY_CODE=1  -s EXPORTED_FUNCTIONS="['_go']"
cp ../../src/html/index.html out/

当我在浏览器中加载程序时,我看到hi there已打印到JS控制台。

但是,在准备使用更高级的代码时,我通过删除-s ONLY_MY_CODE=1条目来更改我的编译脚本。

如果没有对任何文件进行任何进一步更改,当我编译并运行该程序时,我在浏览器中看到以下错误消息:

index.html:1 Uncaught (in promise) LinkError: WebAssembly Instantiation: Import #0 module="env" function="DYNAMICTOP_PTR" error: global import must be a number at <anonymous> Promise rejected (async) (anonymous) @ index.html:35

如何解决此问题?

main.cc

extern "C"
{
    extern void print(char *message);

    void go()
    {
        print("hi there");
    }
}

的index.html

<script>

  var webSocket;
  const memory = new WebAssembly.Memory({ initial: 256, maximum: 256 });
  const buffer = new Uint8Array(memory.buffer);
  var exports;

  function toJsStr(offset){
      var s="";
      for(;;){
          var b = buffer[offset++];
          if( b == 0 )
              return s;
      s += String.fromCharCode(b);  
    }
  } 

  function print(offset){
    console.log(toJsStr(offset));
  }

  fetch('index.wasm').then(response => 
    response.arrayBuffer()
  ).then(bytes => {
      var imports = {};
      imports.env = {};
      imports.env.memory = memory;
      imports.env.memoryBase = 0;
      imports.env.table = new WebAssembly.Table({ initial: 0, maximum: 0, element: 'anyfunc' });
      imports.env.tableBase = 0;
      imports.env._print = print;

      return WebAssembly.instantiate(bytes, imports);
    }
  ).then(module => {
        exports = module.instance.exports; 

        exports._go();
      }
  );
  </script>

1 个答案:

答案 0 :(得分:1)

Emscripten在生成的WASM代码中包含运行时。这个生成的运行时允许它支持广泛的C / C ++特性,使得移植复杂的代码库变得更加容易。这个运行时也有一个JavaScript对应物,所以当你编译一个C / C ++代码库时,你会看到它输出一个wasm文件,一个JavaScript文件和一个HTML文件。 HTML文件是代码的模板化测试工具。

使用@media (max-device-width: 600px) and (orientation: portrait), (max-device-height: 600px) and (orientation: landscape) @media (not (max-device-width: 600px) and (orientation: portrait)) and (not (max-device-height: 600px) and (orientation: landscape)) 进行编译时,您将消除大部分此运行时,因此也不再生成JavaScript和HTML文件。使用ONLY_MY_CODE时,您可以使用的功能非常有限,例如,您不能使用字符串,或者从导出的函数中返回除数字类型之外的任何内容。

因此,在您的示例中,删除ONLY_MY_CODE时,您需要通过生成的JavaScript文件加载您的wasm文件。这将加载wasm代码并处理导出/导入/内存以便结婚&#39;生成的运行时代码。错误消息中显示的函数ONLY_MY_CODE是此运行时的组成部分之一。