The title says it all. When I run the following code:
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE hFile = CreateFile(TEXT(\"Foo.txt\"), GENERIC_WRI
Here's a solution I put together (far from perfect of course). It calls a custom function for every character written to STDOUT. In my example, it forwards the stream to OutputDebugString calls.
#include
#include
#include
#include
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
enum StdHandleToRedirect {
STDOUT, STDERR
};
class StdRedirect {
public:
/// Assumes the specified handle is still assigned to the default FILENO (STDOUT_FILENO/STDERR_FILENO)
/// TODO allow redirection in every case
/// callback will run in a new thread and will be notified of any character input to
/// the specified std handle
StdRedirect(StdHandleToRedirect h, std::function callback) : callback(callback) {
CreatePipe(&readablePipeEnd, &writablePipeEnd, 0, 0);
SetStdHandle(h == STDOUT ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE, writablePipeEnd);
// Redirect (TODO: ERROR CHECKING)
int writablePipeEndFileStream = _open_osfhandle((long)writablePipeEnd, 0);
FILE* writablePipeEndFile = NULL;
writablePipeEndFile = _fdopen(writablePipeEndFileStream, "wt");
_dup2(_fileno(writablePipeEndFile), h == STDOUT ? STDOUT_FILENO : STDERR_FILENO);
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)stdreader, this, 0, 0);
}
// TODO implement destructor, cleanup, reset
private:
// DWORD (WINAPI *PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter)
static void WINAPI stdreader(StdRedirect* redirector) {
while (1) {
char c;
DWORD read;
::fflush(NULL); // force current stdout to become readable
// TODO add error handling
ReadFile(redirector->readablePipeEnd, (void*)&c, 1, &read, 0); // this blocks until input is available
if (read == 1)
redirector->callback(c);
}
}
HANDLE readablePipeEnd, writablePipeEnd;
const std::function callback;
};
int main() {
std::function toOutputDebugString = [](char x) {
char str[2] = {x, 0};
OutputDebugStringA(str);
};
StdRedirect so(STDOUT, toOutputDebugString);
std::cout << "test stdout\n";
while (1); // busy loop to give the thread time to read stdout.
// You might want to look at "Output: Show output from: Debug" now.
return 0;
}