带有模块加载器的 Emscripten
Posted
技术标签:
【中文标题】带有模块加载器的 Emscripten【英文标题】:Emscripten with module loaders 【发布时间】:2015-03-29 12:43:32 【问题描述】:我正在尝试使用 Emscripten 将 C 库转换为可移植的 javascript 模块,该模块将由 AMD(例如 Require.JS)加载并提供对其功能和事物的访问:
require("vendor/mylib.js", function(mylib)
mylib.function1();
);
但是,我看到 Emscripten 使用大量变量污染了全局命名空间,这违背了模块应该独立且不与其他加载的模块发生冲突的前提。
所以问题是:将 Emscrpiten 与 AMD 结合使用的最佳方式是什么?
有没有办法告诉 Emscripten 不要向global
泄露任何内容?
【问题讨论】:
【参考方案1】:emcc docs 中有 2 个命令行选项可以提供帮助,--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 plugin 以便在 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,那么您应该会看到两次“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);
);
【讨论】:
非常有趣,没想到像那样一起使用--pre-js
和--post-js
... 但是我检查了Plunk 并且Module
对象存在于全局命名空间中。我怎样才能避免这种情况?
@jmendeth 我怀疑我是用 Emscripten 的旧版本创建的。包含github.com/kripken/emscripten/commit/… 提交的最新版本我认为不会将Module
对象放在全局命名空间中
根据 FAQ answer,Emscripten 现在有 MODULARIZE
和 EXPORT_NAME
编译标志,看起来很有希望......以上是关于带有模块加载器的 Emscripten的主要内容,如果未能解决你的问题,请参考以下文章