I am playing around with some OpenGL, using SDL to handle the window / input etc. Currently I am displaying any information I want to see to a HUD. Well, this is getting over-cumbersome, and I was wondering if there is a simple way to open up a separate console window to report this information to me. I am still new to C++ so go easy on me if this is an obvious one.
The following code is for Windows. I always find it handy to keep around the ability to create a console window on demand:
int hConHandle;
intptr_t lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
// allocate a console for this app
AllocConsole();
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
coninfo.dwSize.Y = 500;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
// redirect unbuffered STDOUT to the console
lStdHandle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 );
// redirect unbuffered STDIN to the console
lStdHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "r" );
*stdin = *fp;
setvbuf( stdin, NULL, _IONBF, 0 );
// redirect unbuffered STDERR to the console
lStdHandle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stderr = *fp;
setvbuf( stderr, NULL, _IONBF, 0 );
// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog point to console as well
std::ios::sync_with_stdio();
//Keep our window in focus
SetForegroundWindow(m_hWnd); // Slightly Higher Priority
SetFocus(m_hWnd); // Sets Keyboard Focus To The Window
This code assumes that the HWND is in a variable called m_hWnd; it's copied from a class wrapper I use. How you get the HWND from SDL is up to you, however.
To free the console, call this:
FreeConsole();
AllocConsole and FreeConsole are Win32 API functions.
In Linker -> System in your project's properties, check that the SubSystem is "Console (/SUBSYSTEM:CONSOLE)". That causes a separate console window to be brought up when you run your program. If your current entry point isn't main, then you'll need to change it to that if you do this though.
If you're running from a command line and use printf() you should see messages logged out to your terminal window. Otherwise you could log to a file and use tail -f on *nix style boxes to view the output as it appears.
What environment are you using? Most IDEs will show this output in their debug output windows as well.
Related
I followed these instructions to create a console in my Visual Studio 2010 GUI app, and connect up the standard I/O with the console. However, stdin still does not work (although stdout and stderr work perfectly fine). What am I doing wrong?
Here is my version of the code (slightly modified from the answer I linked to above):
static void create_console()
{
AllocConsole();
SetConsoleTitle(L"Python console");
intptr_t stdin_handle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE);
int conin_handle = _open_osfhandle(stdin_handle, _O_TEXT);
FILE *fpin = _fdopen(conin_handle, "r");
*stdout = *fpin;
setvbuf(stdout, nullptr, _IONBF, 0);
intptr_t stdout_handle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
int conout_handle = _open_osfhandle(stdout_handle, _O_TEXT);
FILE *fpout = _fdopen(conout_handle, "w");
*stdout = *fpout;
setvbuf(stdout, nullptr, _IONBF, 0);
intptr_t stderr_handle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE);
int conerr_handle = _open_osfhandle(stderr_handle, _O_TEXT);
FILE *fperr = _fdopen(conerr_handle, "w");
*stderr = *fperr;
setvbuf(stderr, nullptr, _IONBF, 0);
}
One interesting thing I found was that while fileno(stdout) and fileno(stderr) returned normal values, namely 4 and 5, fileno(stdin) returned -2, which is not even a documented error code of fileno (From the doc: "Otherwise, the value -1 is returned and errno is set to indicate the error.").
I'm writing a class to display a custom console from inside the application. I'm also using glog to log messages to a file and at the same time to stderr. How can I have my console class listen to stderr?
I thought of making a custom fstream and the doing something like:
CustomStream cs;
auto original_buf = std::cerr.rdbuf(cs.rdbuf());
and having calls to the stream operator << sent to the console class.
Or subclassing directly from std::filebuf and calling:
CustomFilebuf fb;
auto original_buf = std::cerr.rdbuf(&fb);
Is this the right way to do it? I searched for some sample code but couldn't find very much.
Edit1: I tried using stream tee, but glog logs with stderr and not std::cerr, so I wasn't able to grab any data.
I am uncertain if this is relevant to your question, but...
ISO C99 says in 7.19.5.3, paragraph 6:
When a file is opened with update mode ('+' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function [...], and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
Also some say reading from stderr is "undefined behavior"...
Though you can read from stderr, as long as you flush before reading:
fwrite("x", 1, 1, stderr);
fflush(stderr);
fgetc(stderr);
Also take a look at How do I read stdout/stderr output of a child process correctly?
For anyone who would like to redirect stdout to a console Window in a Win32 app there is
AllocConsole.
I even created a simple (trivial) function to redirect stdout to the console Window:
#include <fstream>
#include <io.h>
#include <fcntl.h>
#define cMaxConsoleLines 500
void ReadyConsole() {
short int hConHandle;
long lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
// Allocate a console for the program
AllocConsole();
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
coninfo.dwSize.Y = cMaxConsoleLines; // The max number of lines for the console!
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
// Redirect STDOUT to the console
lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "w"); // Writing to the console
*stdout = *fp;
setvbuf(stdout, NULL, _IONBF, 0);
// -------------------------------
// Redirect STDIN to the console
lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "r"); // Reading from the console
*stdin = *fp;
setvbuf(stdin, NULL, _IONBF, 0);
// ------------------------------
// Redirect STDERR to the console
lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "w"); // STDERR writing to the console!
*stderr = *fp;
setvbuf(stderr, NULL, _IONBF, 0);
// ------------------------------
// Point the console to STDIO
std::ios::sync_with_stdio();
}
If you would like the console to be for Debug only, make sure to include <crtdbg.h>, which defines whether the app is in debug mode (for VC++), then, for example you could add:
#ifdef _DEBUG
// The file with the ReadyConsole function
#include <DebugStuff.h>
#endif
and to use it
#ifdef _DEBUG
ReadyConsole(); // Ready the console for debugging
#endif
#ifdef _DEBUG
fprintf(stdout, "Position, Line 1, DEBUG-INFO-HERE");
cout << "COUT is working!"; // NOTE, for cout, you will need <iostream>
#endif
Here is an additional little function (it logs the message to both stderr and stderr.log file)
void StdErr(char* Error) {
fprintf(stderr, Error);
FILE* FP = fopen("stderr.log", "a");
fputs(Error, FP);
fclose(FP);
}
A team member added the following code to our GUI Ogre project to add a console (so that we are able to see cout as we are debugging...
We are now running way behind time, and we need text interaction with the game, I was going to make a console, but it is plausibly a big time hole... So I thought hey! Why not use the console he attached!! unfortunatly, I was inable to type into it when I attempted, thus I wouldn't be able to send a command to the console :\
Is there any way to enable writing into the console (atm the way he's done it if you hit any key (as such as 'a') nothing goes into the console, therefore I can't wait for enter and then phase the string typed into the win32 console)
Here's his code (I also added the link encase somone has a rough idea, but they want to read about it again, I don't know the exact guide he followed, but it was very simular)
void showWin32Console()
{
static const WORD MAX_CONSOLE_LINES = 1000;
int hConHandle;
long lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
// allocate a console for this app
AllocConsole();
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
coninfo.dwSize.Y = MAX_CONSOLE_LINES;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
// redirect unbuffered STDOUT to the console
lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 );
// redirect unbuffered STDIN to the console
lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "r" );
*stdin = *fp;
setvbuf( stdin, NULL, _IONBF, 0 );
// redirect unbuffered STDERR to the console
lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stderr = *fp;
setvbuf( stderr, NULL, _IONBF, 0 );
// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
// point to console as well
std::ios::sync_with_stdio();
}
AllocConsole() just gives you a new console, it doesn't change existing stdin/stdout - so the handles you get back from GetStdHandle will still be their former values. Instead you have to open the special devices "CONIN$"/"CONOUT$". Turns out that reassigning stdin/stdout to this new console is actually fairly simple, using freopen:
BOOL f = AllocConsole();
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
...and presto, all further access to standard input or output will now go to your new console.
(This doesn't change what the Win32's view of your standard input/output handles are, by the way, so if there happens to be other code in the process that calls GetStdHandle(STD_INPUT_HANDLE) etc instead of using the CRT's stdio, those will still return the original values that are not related to your new console. If you need to change those too, then you may need to play around with opening CONIN$/CONOUT$ manually and using SetStdHandle to fix up those.)
If no arguments are given to the program it launches as a GUI application, if it is given args it is run through the command line. I was able to get visual studio to display and print to the console with Properties>Linker>SubSystem (Console/SUBSYSTEM:CONSOLE), but this makes it so that the console always displays when the application is launched, how can I selectively display the console so that when the app is run with the GUI it does not appear. I have looked through the site, but all I have found is how to set it to only be a windows application, and I need it to function as both
Thanks!!!
This works I guess:
#include <QtGui/QApplication>
#include <QtGui/QMainWindow>
int
main(int n_app_args, char **app_arg)
{
QCoreApplication * application = 0;
if ( n_app_args == 1 )
{
application = new QCoreApplication(n_app_args, app_arg);
}
else
{
application = new QApplication(n_app_args, app_arg);
QMainWindow * mainWindow = new QMainWindow();
mainWindow->show();
}
return application->exec();
}
Call it with an argument and you get a little (empty) window. Call it with no argument and no window.
Here's some code I had lying around that creates a console and attaches input and output to it:
#include <Windows.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
void Console::createConsole()
{
AllocConsole();
SetConsoleTitle("Debug console");
int hConHandle;
long lStdHandle;
FILE *fp; // redirect unbuffered STDOUT to the console
lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 );
// redirect unbuffered STDIN to the console
lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "r" );
*stdin = *fp;
setvbuf( stdin, NULL, _IONBF, 0 );
// redirect unbuffered STDERR to the console
lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stderr = *fp;
setvbuf( stderr, NULL, _IONBF, 0 );
}
I haven't used Qt but you should be able to stick that somewhere and make it work.
Edit: added the headers needed
You can have it using the windows subsystem, and calling AllocConsole when you need a console while the application has a gui as well.
my wxWidget Application does not make any std::cout << "xyz" ... on a windows console (Windows XP) when it is startet from a console by e.g.: "call MyApplication.exe". It will produce no output at all. The Application instead rises correctly and works fine. All Buttons and Widgets on the Frame have their functions working.
When I run my application from Eclipse, it produces its outputs as it should be to Eclipse' console.
So, why i can't see any output on windows console? What do i have to activate?
I've always been curious about this, so I followed the links provided in Bo Persson's answer and pieced together some code. To use it, just define a UseConsole object in main.
UseConsole.h:
class UseConsole
{
public:
UseConsole();
~UseConsole();
private:
bool m_good;
};
UseConsole.cpp:
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <fstream>
#include "UseConsole.h"
// The following function is taken nearly verbatim from
// http://www.halcyon.com/~ast/dload/guicon.htm
void RedirectIOToConsole()
{
int hConHandle;
long lStdHandle;
FILE *fp;
// redirect unbuffered STDOUT to the console
lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 );
// redirect unbuffered STDIN to the console
lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "r" );
*stdin = *fp;
setvbuf( stdin, NULL, _IONBF, 0 );
// redirect unbuffered STDERR to the console
lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stderr = *fp;
setvbuf( stderr, NULL, _IONBF, 0 );
// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
// point to console as well
std::ios::sync_with_stdio();
}
UseConsole::UseConsole()
{
m_good = !!AttachConsole(ATTACH_PARENT_PROCESS);
if (m_good)
RedirectIOToConsole();
}
UseConsole::~UseConsole()
{
if (m_good)
FreeConsole();
}
A windowed application by default doesn't have a console. You can create one if you like to have one anyway.
See the answers to this question:
Visual C++ Enable Console
When running in an IDE, the IDE often does that for you.
If you already have a console window open, you can alternatively attach to the parent process' console using AttachConsole(ATTACH_PARENT_PROCESS).
http://msdn.microsoft.com/en-us/library/ms681952(v=vs.85).aspx