You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在单个HTML页面中加载多个WebAssembly生成的JS脚本并正常调用?

如何在单个HTML页面中加载多个WebAssembly生成的JS脚本并正常调用?

我来帮你搞定这个问题!你遇到的核心麻烦是,Emscripten默认生成的JS脚本都会去用全局的Module对象,两个脚本同时加载时就会互相干扰,导致初始化冲突,才会弹出那些错误提示。下面给你两种靠谱的解决办法,优先推荐第一种哦:

方案一:给每个WASM模块创建独立的实例(推荐)

Emscripten支持通过编译参数让生成的JS脚本变成模块化的工厂函数,这样每个模块都有自己独立的实例,不会再抢全局对象了。

1. 重新编译第二个WASM项目

编译的时候加上-s MODULARIZE=1 -s EXPORT_NAME='createHello2Module'这两个参数,比如:

emcc your_second_code.c -o hello2.js -s MODULARIZE=1 -s EXPORT_NAME='createHello2Module'

这样生成的hello2.js会暴露一个叫createHello2Module的函数,调用它就能得到一个独立的模块实例,完全不会影响第一个模块的全局Module。

2. 在HTML中使用独立实例

修改你的HTML代码,用工厂函数初始化第二个模块:

<!-- 第一个模块:保持原来的全局Module用法 -->
<script src="hello.js"></script>
<script>
    var js_wrapped_fib = Module.cwrap("fib", "number", ["number"]);
    
    function pressBtn(){
        console.log("The result of fib(5) is:", js_wrapped_fib(5));
    }
</script>
<button onclick="pressBtn()">Click me!</button>

<!-- 第二个模块:使用独立的模块化实例 -->
<script src="hello2.js"></script>
<script>
    // 初始化第二个模块,因为是异步加载WASM,所以用then等待完成
    let hello2Module;
    createHello2Module().then((moduleInstance) => {
        hello2Module = moduleInstance;
        console.log("第二个模块加载完成啦!");
    });
    
    function pressBtn2(){
        if (!hello2Module) {
            console.log("别急,第二个模块还在加载中呢!");
            return;
        }
        const js_wrapped_printout = hello2Module.cwrap("printout", "number", ["number"]);
        console.log("The clicked button got the number:", js_wrapped_printout(6));
    }
</script>
<button onclick="pressBtn2()">Click for number</button>

方案二:临时替换全局Module(适合无法重新编译的场景)

如果你没办法重新编译第二个WASM项目,也可以通过临时替换全局Module对象的方式来隔离两个模块。不过这个方法有一定风险,因为有些Emscripten生成的脚本可能依赖特定的初始化时机,所以优先用方案一哦:

<!-- 第一个模块:正常使用全局Module -->
<script src="hello.js"></script>
<script>
    var js_wrapped_fib = Module.cwrap("fib", "number", ["number"]);
    
    function pressBtn(){
        console.log("The result of fib(5) is:", js_wrapped_fib(5));
    }
</script>
<button onclick="pressBtn()">Click me!</button>

<!-- 第二个模块:临时替换全局Module来隔离 -->
<script>
    // 先把原来的全局Module存起来
    const originalGlobalModule = window.Module;
    // 给第二个脚本创建一个新的空Module对象
    window.Module = {};
</script>
<script src="hello2.js"></script>
<script>
    // 保存第二个模块的实例
    const hello2Module = window.Module;
    // 把全局Module恢复成原来的第一个模块的对象
    window.Module = originalGlobalModule;
    
    function pressBtn2(){
        const js_wrapped_printout = hello2Module.cwrap("printout", "number", ["number"]);
        console.log("The clicked button got the number:", js_wrapped_printout(6));
    }
</script>
<button onclick="pressBtn2()">Click for number</button>

为什么会出现这个错误?

你看到的Module.arguments被替换成arguments_的报错,本质是第一个脚本初始化时已经修改了全局Module的内部结构,第二个脚本加载时还在按照旧的逻辑去访问Module.arguments,但这个属性已经被Emscripten改成arguments_了——说白了就是两个脚本在抢同一个全局Module对象的控制权,互相打乱了对方的初始化流程。

备注:内容来源于stack exchange,提问作者BenjaminHzo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 16:18:03