Windows C ++:如何redirectstderr调用fprintf?

我正在用我们自己的自定义包装器从BSD项目中包装现有的C ++代码,并且希望尽可能less地将其与我们的代码集成。 此代码使用fprintf打印到stderr以logging/报告错误。

我想在相同的过程中将其redirect到另一个地方。 在Unix上,我用socketpair和一个线程完成了这个工作:socket的一端是发送stderr的地方 (通过调用dup2 ),另一端在一个线程中被监视,在那里我可以处理输出。

这不适用于Windows,因为套接字与文件句柄不一样。

我在网上find的所有文件都显示了如何redirectsubprocess的输出,这不是我想要的。 如何在同一个进程中redirectstderr在写入输出时获得某种callback? (在你这么说之前,我已经试过了SetStdHandle但是找不到任何方法来完成这个工作)…

Solutions Collecting From Web of "Windows C ++:如何redirectstderr调用fprintf?"

你可以在Windows上使用类似的技巧,你只需要为同一个概念使用不同的单词。 :)这篇文章: http : //msdn.microsoft.com/en-us/library/ms682499.aspx使用win32管道来处理来自另一个进程的I / O,你只需要做同样的事情在相同的线程处理。 当然,在你的情况下,从进程中的任何地方输出到标准错误将被重定向到你的消费者。

其实,你可能需要的其他部分是_fdopen和_open_osfhandle 。 事实上,下面是我几年前发布的一些代码的一个相关示例:

 DWORD CALLBACK DoDebugThread(void *) { AllocConsole(); SetConsoleTitle("Copilot Debugger"); // The following is a really disgusting hack to make stdin and stdout attach // to the newly created console using the MSVC++ libraries. I hope other // operating systems don't need this kind of kludge.. :) stdout->_file = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT); stdin->_file = _open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE), _O_TEXT); debug(); stdout->_file = -1; stdin->_file = -1; FreeConsole(); CPU_run(); return 0; } 

在这种情况下,主进程是一个GUI进程,它不是以stdio句柄开头的。 它打开一个控制台,然后将右侧的手柄放到标准输出和标准输入中,这样debug()函数(被设计成一个stdio交互式函数)可以和新创建的控制台进行交互。 你应该可以打开一些管道,做同样的事情来重定向stderr。

你必须记住,MSVCRT称之为“OS句柄”的不是Win32句柄,而是添加了另外一层句柄来混淆你。 MSVCRT尝试模拟在stdin = 0, stdout = 1, stderr = 2等等的Unix句柄编号。 Win32句柄的编号是不同的,它们的值总是为4的倍数。打开管道并正确配置所有的句柄将需要弄乱你的手。 使用MSVCRT源代码和调试器可能是一个要求。

你提到你不想在内部使用命名管道; 可能值得一提的是, CreatePipe()的文档声明: “匿名管道是使用具有唯一名称的命名管道实现的,因此,通常可以将一个句柄传递给一个匿名管道,管。” 所以,我建议你只写一个函数来创建一个类似管道的异步读取的正确设置。 我倾向于使用GUID作为字符串(使用CoCreateGUID()StringFromIID() )给我一个唯一的名称,然后使用正确的重叠I / O设置创建命名管道的服务器和客户端(更多详细信息在这里,和代码,在这里: http : //www.lenholgate.com/blog/2008/02/process-management-using-jobs-on-windows.html )。

一旦我有了,我连线一些代码,我必须读取一个文件使用重叠I / O与I / O完成端口,那么,我只是得到数据的异步通知,因为它到达…但是,我已经有相当数量的经过良好测试的库代码在那里,这一切都发生了…

可能可以设置命名管道,然后在OVERLAPPED结构中使用事件重叠读取,并检查事件以查看数据是否可用…我没有任何可用的代码可以这样做。