使用 Emscripten 读写字符串到虚拟文件系统

Read and write string to virtual file system using 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')

当我console.log(Module.FS)时,确实是undefined。此外,console.log(Module) returns {},一个空对象。在 program.js 中,似乎确实通过 Module["FS"] = 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:上面的 main 函数实际上是 运行ning 在一个 worker 上,而不是在 HTML 文档中的脚本标签内。我不能直接编辑 HTML 文件,这就是为什么我 require Emscripten 输出 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