在Win32中重定向标准输出不会重定向标准输出 [英] Redirecting stdout in win32 does not redirect stdout
问题描述
我正在尝试重定向标准输出,以便Windows应用程序中的printf可以转到我选择的文件.
I'm trying to redirect stdout so that printf in a windows application will go to a file of my choice.
我正在这样做:
outFile = fopen("log.txt", "w");
*stdout = *outFile;
setvbuf(stdout, NULL, _IONBF, 0);
但是printf仍会写入控制台(或者在基于GUI的win32应用程序中无处显示)
but printf still writes to the console (or nowhere on a GUI based win32 application)
我可以通过执行以下操作重定向"std :: cout":
I can redirect 'std::cout' by doing this:
outFileStr = std::ofstream(outFile);
std::cout.rdbuf(outFileStr.rdbuf());
但是printf似乎正在做自己的事情.不幸的是,当我试图将python集成到C ++框架中时,我需要重定向printf,这似乎依赖于printf而不是std :: cout.
But printf seems to be doing its own thing. Unfortunately, I need to redirect printf as I'm trying to integrate python in to a C++ framework and that appears to rely on printf rather than std::cout.
std :: cout'似乎已重定向,但不是printf.
std::cout' seems to be redirected but not printf.
推荐答案
由于缺乏在任意Win32文件句柄和更高层文件描述符之间进行映射的适当接口,Windows上重定向标准I/O的工作涉及更多.流.
Redirecting standard I/O is a bit more involved on Windows due to the lack of a proper interface to map between arbitrary Win32 file handles and higher layer file descriptors/streams.
Windows上实际上有三个不同的I/O层:
There are actually three different layers of I/O on Windows:
- 标准吗?C I/O流(这些由
printf
,scanf
等使用) - POSIX I/O描述符(这些是
read
,write
等使用的整数) - Win32 API I/O句柄(由
ReadFile
,WriteFile
,...使用)
- Standard? C I/O streams (these are used by
printf
,scanf
, ...) - POSIX I/O descriptors (these are integers used by
read
,write
, ...) - Win32 API I/O handles (used by
ReadFile
,WriteFile
, ...)
重定向C流
要重定向C流,您可以使用 freopen
一个>.例如,您可以使用以下命令重定向C stdout
:
freopen("log.txt", "w", stdout);
此重定向通常将不重定向由POSIX或Win32 API完成的I/O(如果有的话,它们仍将读/写附加的控制台).此外,子进程不会继承此重定向.(在POSIX兼容/非Windows系统上,通常POSIX API也是系统API,并且C API是在POSIX API之上实现的.在这些情况下, freopen
就足够了)
This redirection will generally not redirect I/O done by POSIX or Win32 APIs (they would still read/write the attached Console, if any). In addition, this redirection will not be inherited by child processes. (On POSIX-compliant/non-Windows systems, it is typical that the POSIX API is also the system API and the C API is implemented on top of the POSIX API. In these cases, freopen
is sufficient.)
要在POSIX API级别上重定向I/O,可以使用 dup2
.例如,您可以重新分配文件描述符 STDOUT_FILENO
来重定向 stdout
,例如:
To redirect I/O at the POSIX API level, you can use dup2
. For example, you can reassign file descriptor STDOUT_FILENO
to redirect stdout
, something like:
int fd = open("log.txt", O_WRONLY);
dup2(fd, STDOUT_FILENO);
close(fd);
不幸的是,在Windows上,即使是POSIX API级别的重定向也不保证C或Win32 API级别的重定向.这是否有效取决于C库实现在POSIX文件描述符和Win32文件句柄之间进行映射所付出的努力(假设您正在使用的C运行时库将其I/O分层放置在POSIX之上).也不能保证此重定向将由派生的子代继承.
Unfortunately on Windows, even redirection at the POSIX API level does not guarantee redirection neither at the C nor the Win32 API levels. Whether this will work or not depends on the effort put in the implementation of the C library to map between POSIX file descriptors and Win32 file handles (presuming the C runtime library you are using layered its I/O on top of POSIX to begin with). There is also no guarantee that this redirection will be inherited by spawned children.
要在Windows上正确重定向I/O,您必须在最低级别(即Win32 API级别)进行重定向,并在更高级别上修复链接,如下所示:
To correctly redirect I/O on Windows you have to redirect at the lowest level (i.e., the Win32 API level) and fix the linkage at higher levels as follows:
- 通过调用
CreateFile
. - 使用将新句柄分配给所需的std I/O设备> SetStdHandle .
- 使用
- Allocate a new handle by calling
CreateFile
. - Assign that new handle to the desired std I/O device using
SetStdHandle
. - Associate that new handle with the corresponding C std file descriptor using
_open_osfhandle
(returns a file descriptor number). - Redirect the returned file descriptor using the
dup2
technique explained above.
以下是重定向 stdout
的示例代码段:
Here is a sample snippet to redirect stdout
:
HANDLE new_stdout = CreateFileA("log.txt", ...);
SetStdHandle(STD_OUTPUT_HANDLE, new_stdout);
int fd = _open_osfhandle(new_stdout, O_WRONLY|O_TEXT);
dup2(fd, STDOUT_FILENO);
close(fd);
P.S.如果您可以在程序内部不进行I/O重定向,则可以使用一个小的批处理文件在命令行上简单地使用控制台的I/O重定向:
P.S. If you can do without I/O redirection inside the program, then you can simply use the Console's I/O redirection at the command line using a tiny Batch file:
@echo off
start "my_gui_app" "path/to/my_gui_app.exe" 1> "path/to/log.txt"
这篇关于在Win32中重定向标准输出不会重定向标准输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!