.wat中(import)的含义及_Znaj导入LinkError问题求助
解决WebAssembly中
_Znaj导入错误及.wat导入语句说明 一、.wat中(import)语句的含义
(import $import0 "env" "_Znaj" (param i32) (result i32))是WebAssembly的导入声明,具体含义:
- 告知Wasm模块,必须从外部环境(此处为JavaScript的
env命名空间)导入一个名为_Znaj的函数 - 该函数接收一个32位整数参数,返回一个32位整数结果
_Znaj是GCC/Clang编译器对C++operator new[](unsigned int)(数组版new运算符)的**名字修饰(Name Mangling)**结果——你的C++代码中使用了new int[amt]做内存分配,编译器将这一操作编译为对_Znaj函数的调用,因此Wasm模块需要外部提供该函数才能正常执行。
二、解决导入错误的两种方案
方案1:在JavaScript的importObject中实现_Znaj函数
直接给importObject的env对象添加_Znaj的实现,该函数需要在Wasm内存中分配指定大小的内存并返回指针。示例代码:
const importObject = { env: { __memory_base: 0, __table_base: 0, memory: new WebAssembly.Memory({initial: 1}), // 实现_Znaj:对应C++的operator new[](unsigned int) _Znaj: function(size) { // 计算需要的字节数(int类型占4字节) const requiredBytes = size * 4; // 检查内存是否足够,不足则按64KB/页扩容 const currentBytes = this.memory.buffer.byteLength; if (this.__memory_base + requiredBytes > currentBytes) { const pagesNeeded = Math.ceil(requiredBytes / 65536); this.memory.grow(pagesNeeded); } // 分配内存并更新内存基址 const ptr = this.__memory_base; this.__memory_base += requiredBytes; return ptr; } } } // 原fetch与实例化代码保持不变 fetch('wasmPrimes.wasm').then((response) => response.arrayBuffer() ).then((bytes) => WebAssembly.instantiate(bytes, importObject) ).then((results) => { primes = results.instance.exports._Z10wasmPrimesi(amt); });
补充:如果后续代码用到
delete[]释放内存,还需要添加对应名字修饰后的函数_ZdaPv(对应operator delete[](void*))的实现。
方案2:修改编译方式,将内存分配逻辑打包进Wasm模块
若不想手动实现内存分配函数,可使用Emscripten等工具将C++标准库的内存分配逻辑编译进Wasm模块,避免依赖外部导入。
以Emscripten为例,编译命令如下:
emcc wasmPrimes.cpp -o wasmPrimes.wasm -s EXPORTED_FUNCTIONS='["_Z10wasmPrimesi"]' -s STANDALONE_WASM=1
-s EXPORTED_FUNCTIONS:指定需要导出到JavaScript的函数(即你的wasmPrimes函数,名字修饰后为_Z10wasmPrimesi)-s STANDALONE_WASM=1:生成独立Wasm模块,包含必要的标准库函数(如内存分配)
编译后生成的Wasm模块无需外部提供_Znaj,直接使用你原来的importObject即可运行。
内容的提问来源于stack exchange,提问作者Luh0
相关产品推荐
相关产品推荐

