我该如何在网页中运行使用Emscripten编译的交互式程序?

14

我有一个简单的程序,例如以下内容:

#include <stdio.h>

int main()
{
    char buf[100];
    while (fgets(buf, sizeof(buf), stdin) != NULL) {
        printf("You typed: %s", buf);
    }
}

我已经使用 Emscripten 进行了编译:

emcc -o hello.html hello.cpp

这给了我一个相当基本的Emscripten生成的网页,其中包含一个用于程序输出的简单窗口。然而,fgets()调用会导致浏览器弹出窗口,可能来自prompt()。我可以输入内容,结果最终会在输出窗口中显示。这不是一个理想的交互体验。
我想要更传统的“控制台”界面,用户可以在终端窗口中交互式地输入以提供输入到交互式程序。
我怀疑解决方案可能类似于JQueryTerminalHyperXterm.js,但到目前为止我还不清楚如何将它们连接到Emscripten编译的程序。
如何为我的Emscripten代码提供“控制台”界面?

我不确定,但我认为emscripted正在使用prompt和console.log函数添加自己的stdout/stdin处理程序,因为这些函数需要是异步的。请在emscripten存储库中检查此问题https://github.com/kripken/emscripten/issues/2272,为了使其工作,您可能需要修改emscripten以输出回调或承诺来处理像这样的代码,并且修改版本的输出可以使用jQuery Terminal。至于XTerm。它被创建为后端tty程序的前端,该程序发送ANSI转义代码,而前端仅用于将按键发送到服务器。 - jcubic
@jcubic:谢谢,你提供的那些问题很有帮助,因为它显示其他人之前也问过这个问题!看起来可能可以使用Web Workers在后台运行emscripten编译的代码,使用前台终端,并传递stdin/stdout消息。刚发现Emscripten API支持Web Worker,所以这肯定已经被探索过了。 - Greg Hewgill
1
问题在于C函数是阻塞的,我查看了输出代码并发现get_char函数在Node中使用readSync,在网站上运行时使用window.prompt,因此worker无法解决问题。你可以将fgets发送到worker,但仍然需要阻止脚本的执行。为了在浏览器中拥有类似终端的外观和感觉,您需要在emscripted本身中具有异步fgets函数。也许尝试在GitHub的emscripten存储库中询问,也许他们有异步代码的解决方案。 - jcubic
1个回答

6
这不完全是您想要的,我认为那是不可能的,但这里有一个异步代码的概念证明,它滥用了C中的fetch API,并在JavaScript中使用代理处理来自C的XHR消息。您可以扩展它以拥有任何需要在JS中完成的异步代码。该示例使用jQuery Terminal,其行为与您的示例C代码完全相同。

https://gist.github.com/jcubic/87f2b4c5ef567be43796e179ca08c0da

我也在emscripten仓库中创建了一个关于异步代码的问题。

编辑: 有人使用这种方法将R编程语言编译为WebAssembly:https://github.com/georgestagg/webR


1
我成功地重构了我的代码,使其与你的原型以相同的方式工作。我会暂时保持这个问题的开放状态,看看是否有其他人有任何想法。 - Greg Hewgill
我在 https://github.com/xloem/emterm 上开始了这个项目。最好只处理非阻塞输入。 - fuzzyTew
@fuzzyTew,您在标题emtern中有一个拼写错误。文档会很好,我不知道该怎么处理这个仓库。 - jcubic
@fuzzyTew 猴子补丁不是好的解决方案,当原始库进行更改并更新您的代码时,您需要维护所有更改。 - jcubic
@jcubic非常抱歉,不确定能否完成这个repo,所以我分享了一个低回答的帖子,让人们有资源。如果您可以运行示例,您就可以看到基本思想。我希望在完成它之后向emscripten提交PR。它被设计为具有可以在PR中使用的文件。 - fuzzyTew
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接