带有模块加载程序的Emscripten

Emscripten with module loaders

本文关键字:Emscripten 程序 加载 模块      更新时间:2023-09-26

我正试图使用Emscripten将C库变成一个可移植的JavaScript模块,它将由AMD(如Require.JS)加载,并提供对其功能和内容的访问:

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

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

所以问题是:将Emscrpiten与AMD一起使用的最佳方法是什么

有没有办法告诉Emscripten不要向global泄露任何信息?

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

例如,您可以有一个的前缀文件

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

和的后缀文件

// postfix.js
  };
});

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

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

然后require模块,使用RequireJS语法:

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

下面是一个更完整的示例,在模块定义对象中设置画布元素。我还包括了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>

这样不仅可以根据您的请求保留全局命名空间,而且如果需要,还可以在页面中同时拥有多个Emscripten支持的画布元素。

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

#include <iostream>
using std::cerr;
int main() {
  cerr << "In C++ main function";
}

如果你加载Plunker,那么你应该看到"在C++主函数中"两次,每个加载的模块一次。

如果您需要访问由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);
});