1. 背景知识介绍
1.Win32 Handles和RTL Handles
标准C定义的文件操作类型为FILE*
Win32 API定义文件操作的类型为 HANDLE, 在Windows平台上, 标准C的输入输出函数是HANDLE实现, 标准C的输入输出FILE* 类型会和相应的HANDLE关联。
标准C函数预定义了三个FILE* 变量: stdin, stdout和stderr
Win32 也分别定义了这三个HANDLE, 可以通过HANDLE GetStdHandle() 函数取得
GetStdHandle 参数:
STD_INPUT_HANDLE
STD_OUTPUT_HANDLE
STD_ERROR_HANDLE
这些HANDLE都可以重定向到文件或者控制台窗口,Win32 GUI程序没有控制台窗口,所以Win32的这三个File HANDLE也没有指向Standard input, output, error, 但是我们可以将这三个 FILE HANDLE重定向到控制台窗口,然后将标准C FILE* 关联到这些HANDLE。然后我们就可以正常使用C标准输入输出函数了。
其他用到的函数
_open_osfhandle() 函数, 返回一个RTL handle, 这个RTL handle与Win32 FILE HANDLE相关联, 通过这个RTL handle重定向I/O
FILE *_fdopen(int fd, const char *mode ); 基于文件描述符打开一个C输入输出流
代码
- #include <stdio.h>
- #include <fcntl.h>
- #include <io.h>
- #include <iostream>
- #include <fstream>
- #include <iostream>
- #ifndef _USE_OLD_IOSTREAMS
- using namespace std;
- #endif
- // maximum mumber of lines the output console should have
- static const WORD MAX_CONSOLE_LINES = 500;
- void RedirectIOToConsole()
- {
- 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
- ios::sync_with_stdio();
- }
测试
- void test()
- {
- int iVar;
- RedirectIOToConsole();
- // test stdio
- fprintf(stdout, "Test output to stdout/n");
- fprintf(stderr, "Test output to stderr/n");
- fprintf(stdout, "Enter an integer to test stdin: ");
- scanf("%d", &iVar);
- printf("You entered %d/n", iVar);
- //test iostreams
- cout << "Test output to cout" << endl;
- cerr << "Test output to cerr" << endl;
- clog << "Test output to clog" << endl;
- cout << "Enter an integer to test cin: ";
- cin >> iVar;
- cout << "You entered " << iVar << endl;
- }
参考
http://www.halcyon.com/~ast/dload/guicon.htm