在Code :: Blocks中的GUI应用程序中使用printf

时间:2016-08-18 10:01:56

标签: c user-interface console codeblocks

我希望能够在我的GUI应用程序中使用控制台中的printf来解决调试问题。我只希望控制台在Debug构建目标中可见,而不是Release构建目标。为此,我右键单击工作区中的项目,选择了属性...并在构建目标选项卡中选择了类型中的控制台应用程序,并选中执行结束时暂停框。完成此操作后,控制台和GUI窗口打开正常,但是当我使用printf时没有任何反应。如何在带控制台的GUI应用程序中使用printf

以下是我使用的代码的相关部分:

SDL_Init(SDL_INIT_VIDEO);
putenv("SDL_VIDEO_CENTERED=center");
SDL_WM_SetCaption("Railroad Builder",NULL);
SDL_WM_SetIcon(IMG_Load(strcat_const(parentFolder(exePath),"/icon.png")),NULL);
SDL_SetVideoMode(MAIN_WINDOW_WIDTH,MAIN_WINDOW_HEIGHT,32,SDL_OPENGL);
int running = 1;
while(running){
    printf("myVar = %d",myVar);
}

myVarint,我想检查调试原因的值。

这个问题与this不同,因为在另一个问题中,他们已经知道在从IDE运行程序时如何在控制台中编写,这个问题是关于如何在控制台中编写所有

1 个答案:

答案 0 :(得分:1)

SDL使用它自己的入口点覆盖程序入口点 有关herethereover there的详细信息。

默认情况下,标准输出(stdout, stdin and stderr)会重定向到文件,这些文件的名称与它们所拥有的流的内容相同。
它们应该在您的程序目录中。

1 - 重定向流

要绕过该行为,您必须在SDL_Init 之后插入以下内容。 如果添加后不起作用,请尝试将其添加到主页的最顶部。

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

如果仍然无效,请尝试。

// Start : edit
SDL_Init (...)
FILE * ctt = fopen("CON", "w" );  // c
// or 
ofstream ctt("CON");  // c++
// End : edit


freopen ("CON", "w", stdout);
freopen ("CON", "r", stdin);
freopen ("CON", "w", stderr);
/* ... */


// Start : edit
fclose (ctt); // c
// or
ctt.close(); // c++
// End : edit

了解CON here

从我看来,似乎" CON"可以用NULL替换 (为了它的价值。

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

freopen方法的另一种变体。

freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);

有关CONOUT $和CONIN $ here的更多信息。

如果您遇到以前的问题并使用GNU / Linux BSD,Solaris,Mac Os等,请尝试以下操作。

freopen ("/dev/tty", "w", stdout);
freopen ("/dev/tty", "r", stdin);
freopen ("/dev/tty", "w", stderr);

应用该方法应该如下面的代码所示。

/* ... */
int main {
    SDL_Init(SDL_INIT_VIDEO);


    /* start : redirecting the streams to the console */
    FILE * ctt = fopen("CON", "w" );  // Edit


    freopen ("CON", "w", stdout);
    freopen ("CON", "r", stdin);
    freopen ("CON", "w", stderr);
    /* end : redirecting the streams to the console */


    /*start : your code */
    putenv("SDL_VIDEO_CENTERED=center");
    SDL_WM_SetCaption("Railroad Builder",NULL);
    SDL_WM_SetIcon(IMG_Load(strcat_const(parentFolder(exePath),
                   "/icon.png")),NULL);
    SDL_SetVideoMode(MAIN_WINDOW_WIDTH,MAIN_WINDOW_HEIGHT,32,
                     SDL_OPENGL);
    int running = 1;
    while(running){
        printf("myVar = %d",myVar);
    }
    /* end : your code */


    /* ... */
    fclose (ctt); // Edit
    /* ... */
}

你可以在SDL faq上找到这个例子。

2 - 更改计划的切入点

您也可以取消定义SDL的主要部分,这样您的主要部分就会被调用 为此,请在main函数之前添加下一条指令。

/*...*/
#ifdef main
    #undef main // Prevent SDL from overriding the program's entry point.
#endif


/***/


int main(int argc, char **argv){
    /*...*/ 
}

/*...*/


#ifdef __MINGW32__ // It can be __MINGW64__. Chose according to your architecture.
    #undef main // Prevent SDL from overriding the program's entry point.
#endif


//or 


#if defined(__MINGW32__) || defined(__MINGW64__)
    #undef main // Prevent SDL from overriding the program's entry point.
#endif


/*...*/


int main(int argc, char **argv){
    /*...*/ 
}

关于MINGW32 and MINGW64

3 - 重建SDL

使用从SDL站点下载的预编译SDLmain.dll二进制文件,您无法阻止将stdout / stderr重定向到文本文件。 你可以做的是使用NO_STDIO_REDIRECT编译器标志自己编译SDLmain,或者根本不使用SDLmain。

请注意,不使用SDLmain会破坏可移植性,不建议这样做。

那说有时将stdout.txt和stderr.txt写入可执行文件所在的目录会更好。

你可以用一点点诡计来做到这一点:

#include "SDL/SDL.h"


#ifdef WIN32
    #include "sdl_winmain.h"
#else
    #include "SDL/SDL_main.h"
#endif

其中sdl_winmain.h位于您自己的项目目录中,是SDL源包中src / main / SDL_win32_main.c的重写副本。这样你仍然可以为其他平台提供可移植性,但是不能在windows中的所有地方获得stdout / stderr文件。

来自SDL faq的内容。有关详细信息,请wiki友好。

3.5来源
在源代码(〜/ SDL2-2.0.4 / include / SDL_main.h)中,我发现了以下内容

#ifndef SDL_MAIN_HANDLED
#if defined(__WIN32__)
/* On Windows SDL provides WinMain(), which parses the command line and passes
   the arguments to your main function.


   If you provide your own WinMain(), you may define SDL_MAIN_HANDLED
 */

source code

的在线副本

如果您没有成功定义NO_STDIO_REDIRECT,请尝试SDL_MAIN_HANDLED。
在SDL-1.2.15(〜/ SDL-1.2.15 / include / SDL / SDL_main.h)中找不到它,但我找到的是

#define main    SDL_main

这似乎与上面的#undef主要方法一致。

4 - 注意
将错误消息发送到stderr而不是stdout可能会很有趣。为此,请尝试使用perrorfprintf 像这样:

/*...*/
perror ("Error"); // the string cannot be formatted 
fprintf (stderr,"Error %s", str_err_msg); // the string can be formatted
/*...*/