[SOLVED]Qt capture stdout
-
Don't know if you can do that with Qt only, but with the Win32 API this should work:
@#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <Windows.h>//Create a new pipe
HANDLE hRead;
HANDLE hWrite;
if(!CreatePipe(&hRead, &hWrite, NULL, NULL))
{
fprintf(stderr, "FATAL: CreatePipe failed !!!\n");
_exit(42);
}//Get C-style FILE* pointers from OS handles
int iReadDescr = _open_osfhandle((intptr_t) hRead, _O_RDONLY|_O_BINARY);
int iWriteDescr = _open_osfhandle((intptr_t) hWrite, _O_WRONLY|_O_BINARY);
FILE *fRead = (iReadDescr >= 0) ? _fdopen(iReadDescr, "rb") : NULL;
FILE *fWrite = (iWriteDescr >= 0) ? _fdopen(iWriteDescr, "wb") : NULL;//Set stdout and stderr
*stdout = *fWrite;
*stderr = *fWrite;/* --- the following is for test only --- */
//Create some test output on stdout
printf("Hallo Welt!");
fflush(stdout); //Don't forget to flush or the fread() below will hang forever !!!//Get output from pipe (use DbgView to display!)
for(;;)
{
char buff[2] = {'\0', '\0'};
int len = fread(buff, sizeof(char), 1, fRead);
if(len > 0) OutputDebugStringA(buff);
}@Better solution, of course, would be to modify the code of your "interpreter" to NOT using printf(), but using fprintf() instead with a user-defined stream (can be set via some API and may still default to stdout). Or even better: Use a user-defined logging function (can be set via some API and may still default to printf).
-
master of disaster
Thanks for your effort. Code is weird indeed, but unfortunately not working. I tried using the following code:@printf("aaaaaaaaaaaa"); // Also tried moving it after stdout is open with QFile
QFile file;
file.open(stdout, QIODevice::ReadOnly);QFile result("result.txt");
result.open(QIODevice::WriteOnly | QIODevice::Text);QTextStream txtStream(&result);
txtStream << file.readAll(); // I get around 200 lines of NUL code in notepad++result.close();
file.close();@MuldeR
Thanks. I'll try your code, but if will work, It'll be a temporary solutions, as the program is meant to be cross platform (desktop OSs).
Do you maybe know how Qt Creator starts the app? In worst case, I could start it the same way ( but I assume I might get performance decrease).I'll also take a look at option of modifying the interpreter and writing user-defined a stream.
-
If it can not be done with Qt entirely, you may need to write platform-specific code for each OS.
...or do it properly and modify the "interpreter" code to set a user-define logging function (should be the best).
Note that I have just update the code that I posted above a bit!
-
And if you don't want your fread() to block until there's new data to read, use a separate thread:
@void reader_func(void *handle)
{
char line[2048];
size_t linepos = 0;//Read output and process (use DbgView to display!) for(;;) { //Read next char char buff; int len = fread(&buff, sizeof(char), 1, *((FILE**)handle)); //If successfull, append to line buffer if(len == 1) { line[linepos++] = buff; //If end of line, do output & reset if(buff == '\r' || buff == '\n' || buff == '\b') { if(linepos > 1) { line[linepos-1] = '\n'; //Set last char to line-break line[linepos++] = '\0'; //Append NULL terminator OutputDebugStringA(line); } linepos = 0; } } }
}
int main(...)
{
//Setup stdout/stderr as shown before
/* ... *///Start reader thread _beginthread(reader_func, 0, &fRead); //Create some test output on stdout printf("Hallo Welt!\n"); fflush(stdout); //Don't forget to flush !!! Sleep(5000); printf("Tschüss!\n"); fflush(stdout); //Don't forget to flush !!! Sleep(1000);
}@
-
After further tests, I found out, that stdout already starts closed with a program run as standalone. I did not found a solution (platform independent) to reopen it.
I'll go with a solution of modifying source code of the interpreter -> printf to fprintf as you recommended (done). For opening stream into memory instead into a file I planed to use fmemopen. But after after making a test project of use a fmemopen function ( code from "here":http://pubs.opengroup.org/onlinepubs/9699919799/functions/fmemopen.html), I get an error that fmemopen was not declared.
After further searching I did not find any other useful with same functionality. Is there an alternative function or a different way? -
I don't think fmemopen() is a standard C/C++ function. It's probably not portable!
Well, I already gave you some code that creates a Pipe and gives you C-style FILE* pointers to it.
That code is for Win32 only though. You need to figure out an implementation for Unix/Linux.
But: If you modify the code anyway, why not have your "interpreter" take a logging function as parameter?
You could pass a function pointer to a user-defined function, so you won't even need a stream.
And, as we are on the Qt forums here, why not use Signals & Slots ???
You could give your "interpreter" class a lineLogged(QString &) Signal that will be emitted to log some line.
The "main" program would simply connect to that signal and process the output in a suitable Slot function.
-
I figured that out after further searching through the web.
I wanted to stay with streams, because rest of the program is already bound to that chunk of code. Now I'll have to do a few changes ( 10 lines of code is 10 lines of code ;) ).
Interpreter is written in pure C ( not my work, external library), so implementing signals and slots wouldn't be so easy. Replacing all printfs is already pain in the ...
I decided to change print function of the interpreter, so that it will save output to a variable from which I'll later read.Thanks for all the help!
Marked as solved.
Regards,
Jake -
[quote author="Jake007" date="1356631812"]I figured that out after further searching through the web.
I wanted to stay with streams, because rest of the program is already bound to that chunk of code. Now I'll have to do a few changes ( 10 lines of code is 10 lines of code ;) ).
Interpreter is written in pure C ( not my work, external library), so implementing signals and slots wouldn't be so easy. Replacing all printfs is already pain in the ...
I decided to change print function of the interpreter, so that it will save output to a variable from which I'll later read.Thanks for all the help!
Marked as solved.
Regards,
Jake [/quote]I just wanted you to know that your work here was not in vain, I have the EXACT same problem, and the posts here have helped solve my problem as well, so thanks. (replacing stream with memory stream, replacing printf with fprintf)
-
I seem to have the exact same problem as well, posted just "here":http://qt-project.org/forums/viewthread/40286/.
However, I am not quite sure which changes exactly I have to do.
Would you mind recap shortly?
Thanks
McL