【问题标题】:SDL Console output works when debuging, but not when run with the exeSDL 控制台输出在调试时有效,但在使用 exe 运行时无效
【发布时间】:2013-01-29 23:09:10
【问题描述】:

我正在编写一个实验性网络程序,基本上是一个用于学习网络的测试程序。我在带有 mingw 的 Code::Blocks 中使用 SDL 和 SDL_net,因此控制台输出被定向到 stdout.txt。我四处搜索,发现您可以通过在 SDL_Init() 之后添加来解决此问题:

freopen("CON", "w", stdout); //stops redirect of output
freopen("CON", "w", stderr); //and errors...

这工作得很好,但只有在 IDE 中构建和运行程序时:当在 IDE 之外运行时(例如双击程序),程序运行正常,除了控制台输出,它仍然是空白的.由于该程序应该是一个控制台程序,这是一个严重的问题......我不想总是在 IDE 中运行该程序才能使用它。

任何解决方案都值得赞赏,但我更希望它是对代码的更改,尽管在紧要关头一个批处理文件就可以了(我已经阅读了几篇文章,其中这是唯一有效的方法,但他们没有' 没有详细说明,所以我无法复制它)。谢谢。

【问题讨论】:

    标签: c++ console sdl codeblocks freopen


    【解决方案1】:

    适用于 (MinGW) SDL 2.0 用户

    SDL 2.0 默认禁用控制台,或者更确切地说,它不启用它。 由于使用 -mwindows 编译会禁用控制台,因此 stdout 不会指向任何内容。 SDL_Log 有点花哨,可以使用 windows API 找到控制台,但它无法捕获标准输入,因为 cmd.exe 偷了它:(。

    出于各种原因,SDL 没有声明控制台,很可能是因为该程序是使用 -mwindows 编译的。指定WinMain 作为入口点也可能使cmd.exe 回收控制台。从我读到的SDL_main 可能会重定向标准输出和标准错误。

    您可能会逃脱 #undef'ing main 和/或

    • SDL_init(...); 之后致电AllocConsole();
    • 使用freopen("CON", stdout)
    • 编译不使用-mwindows#undef'ing main似乎没有任何效果)

    但你真的应该将标准输出重定向到例如猫,main | cat(始终遵循规则“不要#undef main,除非你必须这样做”)。

    TL;博士

    要为 MinGW 捕获 stdout,只需将您的程序重定向到 catmain | cat。这是一个 hack,它只是确保 stdout 和 stderr 不会指向任何内容。
    要同时捕获 stdinstdout,请在不使用 -mwindows 的情况下进行编译以创建 Windows 控制台应用程序。如有必要,这将打开一个新窗口。

    注意:使用上述方法之一时,刷新输出尤为重要。无论如何,依赖行缓冲是不好的做法。

    【讨论】:

      【解决方案2】:

      (我昨天不能发这个,因为我没有足够的声望)

      好的,对批处理文件的行做了一些试验。我的结果和(几乎)工作批处理文件:

      program.exe
      

      没想到会这么简单,但还是不明白为什么双击程序不起作用。我说几乎可以工作,因为在客户端连接到服务器后控制台空白,所以仍然存在问题。所以,对于这个问题,我仍然非常感谢任何帮助。

      (昨天的预期帖子结束)

      (今天的回答开始)

      我尝试了 Emartel 的建议,但仍然无效。做了一些测试,发现打印空字符串的无限循环导致连接客户端后出现黑屏问题。修复了循环,现在它可以正常工作了,尽管我仍然必须使用批处理脚本。

      如果有人弄清楚为什么双击不起作用,将不胜感激。

      【讨论】:

        【解决方案3】:

        你看过SDL Console FAQ吗?

        他们提供了许多建议,包括:

        第一次尝试

        freopen( "CON", "w", stdout );
        freopen( "CON", "w", stderr );
        

        如果它不起作用(如您的情况),请尝试

        #include <fstream>
        #include <iostream>
        using namespace std;
        ....
        ofstream ctt("CON");
        freopen( "CON", "w", stdout );
        freopen( "CON", "w", stderr );
        ...
        ctt.close();
        

        FILE * ctt = fopen("CON", "w" );
        freopen( "CON", "w", stdout );
        freopen( "CON", "w", stderr );
        ...
        ctt.close();
        

        另一种选择是重新编译SDLmain 库或将SDLmain 代码添加到您的项目并停止链接到该库。

        【讨论】:

        • (无法编辑评论)感谢您的回复,那篇文章实际上是我获取代码的地方,但我应该先尝试其他两种方法。再次感谢!
        • 其他方法对你有用吗?重建 SDLmain 可能会很痛苦,但希望其他解决方案有效! - 没关系,刚刚看到你的另一个帖子,你尝试重建 SDLMain 吗?
        • 不,我没有...一方面我没有足够的经验来做这件事,另一方面批处理文件现在可以正常工作,但我可能会在某个时候调查一下。您是否只是像普通代码一样编译它(编译成 .o 文件?)
        • 是的,如果我没记错的话,你应该能够让项目在他们的 Mercurial 存储库上构建它
        • 我会调查的,谢谢!
        【解决方案4】:

        两个原因:

        • 使用 SDL,控制台被禁用。 SDL 使用窗口,而不是控制台。

        • SDL 将标准输出(cout 和 printf())重定向到与 *.exe 所在目录相同的文件夹中名为 stdout.txt 的文件。

        你可以使用:

        std::cout << "Hello World";
        

        并且消息将存储在文件stdout.txt中。

        【讨论】:

        • 坦率地说,这似乎不适用于 Debian 存储库中的版本。我没有得到这样的文件,std::cout 工作得很好。 printf 是导致问题的原因。所以还是说要看发货的版本吧。
        猜你喜欢
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-09
        • 2017-09-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多