你可以考虑在运行时使用JavaScript来获取'bundle.zip'文件,然后使用Emscripten文件系统API使其对你的WebAssembly模块可访问。
这样,你可以在不重新编译WebAssembly模块的情况下更改'bundle.zip'文件。
+-------------+ +-----------------+ +-------------+
| C++ Project | --> | Compile to WASM | --> | Web Browser |
+-------------+ +-----------------+ +-------------+
| | |
| | |
| | +-- Fetch bundle.zip
| | | at runtime
| | |
| | +-- Write to Virtual FS
| | | (Emscripten FS API)
| | |
| | +-- Access via fopen()
首先,从你的 Emscripten 构建命令中移除
--embed-file
标志。这将停止将 'bundle.zip' 嵌入到你的 WebAssembly 模块中。
检查一下,如评论所述,
Emscripten » Porting » Files and File Systems » Packaging Files 中提到的
--preload-file
选项是否可行。
在使用 Emscripten 编译你的项目时,使用
--preload-file
标志,后面跟上 '
bundle.zip
' 的路径。然后,Emscripten 会在你的 '
.wasm
' 和 '
.js
' 文件旁生成一个 '
.data
' 文件。
emcc your_project.cpp -o your_project.html --preload-file path/to/bundle.zip
生成的JavaScript加载器代码将在加载WebAssembly模块时自动获取“.data”文件。这意味着“bundle.zip”将与您的“.wasm”文件分开下载,但对于您的应用程序来说,这是透明的。
“bundle.zip”的内容将在运行时自动解压到Emscripten虚拟文件系统中。然后,您的应用程序应使用fopen来访问这些文件,就像它们在常规文件系统上一样。
要更新“bundle.zip”,您只需在服务器上替换“.data”文件。除非C++代码本身发生更改,否则无需重新编译WebAssembly模块。
或者在网页加载时使用JavaScript获取'bundle.zip'。您可以使用
fetch
API来实现这一点。
在调用WebAssembly模块中需要'bundle.zip'的任何函数之前,请确保挂载一个虚拟文件系统并将获取的文件写入其中:这将使'bundle.zip'可访问,就像它是普通文件系统的一部分一样。
您的C++代码现在应该能够使用
fopen
打开'bundle.zip',就像在本地文件系统上一样。
fetch('path/to/bundle.zip')
.then(response => response.arrayBuffer())
.then(data => {
var uint8View = new Uint8Array(data);
FS.writeFile('/bundle.zip', uint8View);
})
.catch(err => console.error('Error fetching bundle.zip:', err));
FS.writeFile
(Emscripten文件系统API的一部分)用于将获取的文件写入Emscripten虚拟文件系统。
OP的答案提出了一个很好的解决方案的实现。
在<head>
部分使用<link rel="preload" href="/bundle.zip" as="fetch" ...>
提示浏览器'bundle.zip
'是一个即将需要的资源,这可以提高加载性能,因为浏览器可以在页面加载过程中尽早开始获取它。
在HTML主体中设置了一个<canvas>
元素,很可能用于渲染来自WebAssembly模块的内容。
CSS确保了一致的盒模型,并重置了默认的边距,同时为canvas和容器元素设置了样式。
Module
对象正确配置了canvas
元素,并将noInitialRun
设置为true
,表示WebAssembly模块不应立即在加载时运行。使用onRuntimeInitialized
回调在WebAssembly环境初始化后获取'bundle.zip
'。
fetch
API 用于将 'bundle.zip
' 加载到 ArrayBuffer 中。然后将该缓冲区转换为 Uint8Array,并使用 FS.writeFile
写入到 Emscripten 虚拟文件系统的路径 '/bundle.zip
'。一旦 'bundle.zip
' 被写入文件系统,就会调用 Module.callMain()
来启动主应用程序。
最后,包含了脚本 carimbo.js
,这很可能是由 Emscripten 生成的 JavaScript,负责加载和运行 WebAssembly 模块。
--preload-file
不就是做这个的吗? - undefined