在Win32中重定向标准输出不会重定向标准输出 [英] Redirecting stdout in win32 does not redirect stdout

查看:95
本文介绍了在Win32中重定向标准输出不会重定向标准输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试重定向标准输出,以便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:

  1. 标准吗?C I/O流(这些由 printf scanf 等使用)
  2. POSIX I/O描述符(这些是 read write 等使用的整数)
  3. Win32 API I/O句柄(由 ReadFile WriteFile ,...使用)
  1. Standard? C I/O streams (these are used by printf, scanf, ...)
  2. POSIX I/O descriptors (these are integers used by read, write, ...)
  3. 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:

  1. 通过调用 CreateFile .
  2. 使用将新句柄分配给所需的std I/O设备> SetStdHandle .
  3. 使用
  1. Allocate a new handle by calling CreateFile.
  2. Assign that new handle to the desired std I/O device using SetStdHandle.
  3. Associate that new handle with the corresponding C std file descriptor using _open_osfhandle (returns a file descriptor number).
  4. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆