我正在尝试使用Emscripten将C库转换为可移植的JavaScript模块,该模块将由AMD(例如Require.JS)加载并提供对其功能和事物的访问:
require("vendor/mylib.js", function(mylib) {
mylib.function1();
});
但是,我已经看到Emscripten用大量变量污染全局命名空间,这违背了模块应该独立且不与其他已加载模块冲突的前提。
所以问题是:在AMD中使用Emscrpiten的最佳方式是什么?
有没有办法告诉Emscripten不要泄漏任何东西到global
?
答案 0 :(得分:5)
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 ...});
});
更完整的示例,在模块定义对象中设置canvas元素如下。我还包括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,那么您应该看到&#34;在C ++主函数&#34;两次,每个加载模块一次。
如果您需要访问由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);
});