[SOLVED]Qt capture stdout
-
Well, then you could try some other hacking, but I'm not sure if it will work.
@
fpos_t pos;fgetpos(stdout, &pos);
@Now you have the current position of the text cursor (the beginning of the following output). Then you run the program.
Now it's time to get the output. We reset the position to the position where the output starts and then read everything to the end:
@
FILE *f = stdout;
fsetpos(f, &pos);QFile file(f);
QByteArray output = file.readAll();
@Some weird code, but it might even work...
-
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