使用Emscripten读取字符串并将其写入虚拟文件系统



我有一个C++程序,它接受两个文件作为输入,并生成一个文件作为输出。这些文件包含字符串。我使用带有以下标志的Emscripten成功地将此程序编译为webassembly:

emcc program.bc -o program.js -s USE_ZLIB=1 -s EXPORTED_RUNTIME_METHODS="['FS', 'callMain']" -s ALLOW_MEMORY_GROWTH=1 -s ENVIRONMENT='web, worker'

然后,我使用以下粘合代码将字符串(作为参数传递(写入Emscripten虚拟文件系统中的文件。然后使用这些文件来运行program的主要功能。然后从文件系统读取输出文件,并将其内容记录到控制台:

const Module = require('./program.js')
async function main(input1, input2){
Module.FS.writeFile('first_input.txt', input1)
Module.FS.writeFile('second_input.txt', input2)
Module.callMain(['-r', 'first_input.txt', '-q', 'second_input.txt', '-o', 'test.out', '-t', '1'])
const output = Module.FS.readFile('test.out', { encoding: 'utf8' })
console.log(output)
}
module.exports = main

当尝试调用上述主函数时,我得到错误:

Unhandled Rejection (TypeError): Cannot read properties of undefined (reading 'writeFile')

当Iconsole.log(Module.FS)时,它确实是未定义的。此外,console.log(Module)返回空对象{}。在program.js中,FS模块似乎是通过Module["FS"] = FS启用的。当我为节点环境(使用-s ENVIRONMENT='node'(编译它时,它可以顺利工作。

为什么它对工人环境不起作用?我能做些什么来修复它?

编辑:我试图将代码包装在"onRuntimeInitialized"函数中,但我得到了相同的错误:

const Module = require('./program.js')
async function main(input1, input2){
Module.onRuntimeInitialized = () => {
Module.FS.writeFile('first_input.txt', input1)
Module.FS.writeFile('second_input.txt', input2)
Module.callMain(['-r', 'first_input.txt', '-q', 'second_input.txt', '-o', 'test.out', '-t', '1'])
const output = Module.FS.readFile('test.out', { encoding: 'utf8' })
console.log(output)
}

await Module.onRuntimeInitialized()
}
module.exports = main

EDIT2:上面的主函数实际上是在worker上运行的,而不是在HTML文档中的脚本标记内部。我不能直接编辑HTML文档,这就是我requireEmscripten输出JavaScript文件的原因。

解决方案是:

  1. 使用MODULARIZE=1标志编译程序
emcc program.bc -o program.js -s USE_ZLIB=1 -s EXPORTED_RUNTIME_METHODS="['FS', 'callMain']" -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s EXPORT_NAME='createModule'
  1. 导入模块,然后等待生成的promise
import createModule from './program.js'
async function main(input1, input2){
const Module = await createModule()
Module.FS.writeFile('first_input.txt', input1)
Module.FS.writeFile('second_input.txt', input2)
Module.callMain(['-r', 'first_input.txt', '-q', 'second_input.txt', '-o', 'test.out', '-t', '1'])
const output = Module.FS.readFile('test.out', { encoding: 'utf8' })
console.log(output)
}

export default main