这是我的第一个问题!
我打算将一些可以正常工作的C ++代码从UNIX移植到Windows,这将通过管道将stdout和stderr重定向到自定义GUI组件。我需要它来显示来自第三方库的反馈,该库仅在GUI上将消息输出到stdout。
根据此答案https://stackoverflow.com/a/617158,此方法应该有效。实际上,来自链接的代码在使用Visual Studio 2017构建的全新命令行应用程序中按预期工作。但是,在我现有的GUI应用程序中,对_fileno(stdout)
和_fileno(stderr)
的调用都返回-2期望值1和2中的任何一个,因此什么也没有发生。对相关功能进行硬编码1和2也不起作用。
任何人都可以解释
为您提供信息,到目前为止,我已经收集了我在Linux和Mac OS上进行编程的主要经验,因此对于有经验的Windows用户而言,这可能是显而易见的。 GUI应用程序基于JUCE框架,因此我使用的是JUCE工具Projucer创建的自动生成的Visual Studio项目
答案 0 :(得分:3)
与Unix类型的系统不同,在Windows中,控制台应用程序和GUI应用程序是两个不同的东西。 GUI应用程序没有stdin,stdout或stderr的概念-它们仅了解Windows,文本框等。
documentation for _fileno says:
如果stdout或stderr与输出流不关联(对于 例如,在没有控制台窗口的Windows应用程序中,该文件 返回的描述符是-2。
因此,如果要使用stdout和stderr,则需要将应用程序构建为控制台应用程序(仍然可以使用GUI)。
另一种方法是继续将应用程序构建为GUI,但可以通过在应用程序开始时调用AllocConsole()来分配控制台(即,在WinMain()
中要做的第一件事),然后然后关联stdout和stderr文件:
if(AllocConsole()){
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
}
答案 1 :(得分:1)
我使用AllocConsole方法@DodgyCodeException提出了建议。最后,我现在在GUI组件的构造函数中调用以下代码以启动控制台并立即将其隐藏,以使用户不会被空的控制台窗口所迷惑:
if(AllocConsole())
{
freopen ("CONOUT$", "w", stdout);
freopen ("CONOUT$", "w", stderr);
ShowWindow (FindWindowA ("ConsoleWindowClass", NULL), false);
}
这在运行时效果很好,例如这样,直到构造相应的GUI组件时才调用它。此外,这种方法使代码对我而言更具可重用性,因为将其包含在其他项目中并不需要添加源文件,而不必在意修改构建时间设置。