Emscripten与模块加载器

Alb*_*dez 2 javascript module emscripten

我正在尝试使用Emscripten将C库转换为可移植的JavaScript模块,该模块将由AMD(例如Require.JS)加载并提供对其功能和事物的访问:

require("vendor/mylib.js", function(mylib) {
    mylib.function1();
});
Run Code Online (Sandbox Code Playgroud)

但是,我已经看到Emscripten使用大量变量污染全局命名空间,这违背了模块应该独立且不与其他已加载模块冲突的前提.

所以问题是:在AMD使用Emscrpiten的最佳方法什么?

有没有办法告诉Emscripten不泄漏任何东西global

Mic*_*mza 5

emcc文档中有2个命令行选项可以提供帮助,--pre-js <file>以及--post-js <file>.它们允许您包装生成的代码,因此允许您与AMD集成.

例如,您可以使用前缀文件

// prefix.js
define(function() {
  return function(Module) {
Run Code Online (Sandbox Code Playgroud)

和后缀文件

// postfix.js
  };
});
Run Code Online (Sandbox Code Playgroud)

你可以编译输出到myModule.js使用类似的东西

emcc --pre-js prefix.js --post-js postfix.js -o myModule.js myModule.cpp
Run Code Online (Sandbox Code Playgroud)

然后require使用RequireJS语法模块:

require(['myModule'], function(myModule) {
  myModule({... Module definition object ...});
});
Run Code Online (Sandbox Code Playgroud)

更完整的示例,在模块定义对象中设置canvas元素如下.我还包括domReady插件,以便在DOM准备好时抓取元素.

<!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>
Run Code Online (Sandbox Code Playgroud)

这样不仅可以保留您请求的全局命名空间,还可以让您在需要时在页面中同时拥有多个基于Emscripten的画布元素.

可以在http://plnkr.co/edit/8jE3uLwrlszQuHbixU68?p=preview上看到上面的HTML页面.它加载一个C++程序:

#include <iostream>
using std::cerr;

int main() {
  cerr << "In C++ main function";
}
Run Code Online (Sandbox Code Playgroud)

如果你加载了Plunker,那么你应该看两次"In C++ main function",每个加载模块一次.

如果您需要访问由Emscripten修改的Module对象,比如调用公开的库函数,您可以执行以下操作,等待Emscripten本身使用以下monitorRunDependencies选项加载的所有依赖项:

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);
});
Run Code Online (Sandbox Code Playgroud)

  • 根据这个[常见问题解答](http://kripken.github.io/emscripten-site/docs/getting_started/FAQ.html#can-i-use-multiple-emscripten-compiled-programs-on-one-web- page),Emscripten 现在有 `MODULARIZE` 和 `EXPORT_NAME` 编译标志,看起来很有希望...... (2认同)