我希望能够在我的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);
}
myVar
是int
,我想检查调试原因的值。
这个问题与this不同,因为在另一个问题中,他们已经知道在从IDE运行程序时如何在控制台中编写,这个问题是关于如何在控制台中编写所有
答案 0 :(得分:1)
SDL使用它自己的入口点覆盖程序入口点 有关here,there和over 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){
/*...*/
}
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文件。
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
*/
的在线副本
如果您没有成功定义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可能会很有趣。为此,请尝试使用perror或fprintf
像这样:
/*...*/
perror ("Error"); // the string cannot be formatted
fprintf (stderr,"Error %s", str_err_msg); // the string can be formatted
/*...*/