Emscripten with module loaders

微笑、不失礼 提交于 2020-01-01 18:58:28

问题


I'm trying to use Emscripten to turn a C library into a portable JavaScript module, that will be loaded by an AMD (such as Require.JS) and provide access to its functions and things:

require("vendor/mylib.js", function(mylib) {
    mylib.function1();
});

However, I've seen that Emscripten pollutes the global namespace with lots of variables, which is against the premise that modules should be independent and not collide with other loaded modules.

So the question is: What's the best way to use Emscrpiten with AMDs?

Is there a way I can tell Emscripten to not leak anything to global?


回答1:


There are 2 command line options from the emcc docs that can help, --pre-js <file> and --post-js <file>. They allow you to wrap the generated code, and so allows you to integrate with AMDs.

For example, you could have a prefix file of

// prefix.js
define(function() {
  return function(Module) {

and a postfix file of

// postfix.js
  };
});

which you would compile outputting to myModule.js using something like

emcc --pre-js prefix.js --post-js postfix.js -o myModule.js myModule.cpp

and then require the module, using the RequireJS syntax:

require(['myModule'], function(myModule) {
  myModule({... Module definition object ...});
});

A fuller example, setting a canvas element in the module definition object follows. I'm also including the domReady plugin to be able to grab elements when the DOM is ready.

<!DOCTYPE html>
<html>
  <head>
    <script src="require.js"></script>
    <script>
      require(['domReady', 'myModule'], function(domReady, myModule) {
        domReady(function() {
          myModule({
            canvas: document.getElementById('canvas_1')
          });
          myModule({
            canvas: document.getElementById('canvas_2')
          });
        });
      });
    </script>
  </head>
  <body>
    <canvas id="canvas_1"></canvas>
    <canvas id="canvas_2"></canvas>
  </body>
</html>

This then not only preserves the global namespace as you requested, but also allows you to have more than one Emscripten-powered canvas element in the page at once, if you need to.

The above HTML page can be seen working at http://plnkr.co/edit/8jE3uLwrlszQuHbixU68?p=preview . It loads a C++ program:

#include <iostream>
using std::cerr;

int main() {
  cerr << "In C++ main function";
}

If you load the Plunker, then you should see "In C++ main function" twice, once for each loaded module.

If you need access to the Module object amended by Emscripten, say to call exposed library functions, you can do something like the following, waiting for all dependencies that Emscripten itself loads using the monitorRunDependencies option:

require(['myModule'], function(myModule) {
  var moduleDef = {
    monitorRunDependencies: function(numberOfDependenciesRemaining) {
      if (numberOfDependenciesRemaining) return;
      // At this point we can call functions added to moduleDef
      // such as cwrap or ccall
    }
  }
  myModule(moduleDef);
});


来源:https://stackoverflow.com/questions/29329240/emscripten-with-module-loaders

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!