How to redirect printf to QTextEdit?
Hi guys, I'm developing a desktop gui app which uses an open source library. The library uses a lot of "printf" statements, which are not seen on my app gui. So I thought of redirecting the printf to a QTextEdit on my app, but don't know how to do it. Till now I found a post on redirection of std::cout to a QTextEdit (http://stackoverflow.com/questions/1...to-a-qtextedit) which works ok, but I'd like to make something similar for "printf". Do you know how to do it (s short sample code would be perfect)? Is it possible at all? If not, what are the alternatives? Much thanks in advance.
Re: How to redirect printf to QTextEdit?
Probably there is a better way, but this seems to be working:
1. redirect stdout to file (freopen)
2. disable buffering (setvbuf)
3. watch for changes with QFileSystemWatcher
ok, this is kind of "sledgehammer to crack a wallnut" thing (see "notes" section in QFileSystemWatcher documentation), but maybe you can use it until someone comes with a better solution
here is some code (tested only on linux):
Code:
// widget.h
include <QPushButton>
#include <QFileSystemWatcher>
#include <QMessageBox>
#include <cstdio>
Q_OBJECT
public:
explicit Widget
(const QString
& fileName,
QWidget * parent
= NULL) ,_nBytes(0)
{
connect(btn, SIGNAL(clicked()), this, SLOT(onClick()));
watcher->addPath(fileName);
connect(watcher,
SIGNAL(fileChanged
(QString)),
this,
SLOT(fileChanged
(QString)));
}
private slots:
void onClick(){
static int counter = 0;
printf("text (%i)",counter++);
}
void fileChanged(const QString& path){
f.seek(_nBytes);
_nBytes += ba.size();
QMessageBox::information(this,
"stdout",path
+ " changed:\n\n" + ba
);
} else {
}
}
private:
int _nBytes;
};
#endif
// main.cpp
#include <QApplication>
#include <cstdio>
#include "widget.h"
int main(int argc, char ** argv){
stdout = freopen("test.txt","w",stdout);
setvbuf(stdout, NULL, _IONBF, 0);
Widget w("test.txt");
w.show();
return app.exec();
}
As my first programming teacher always said (quoting B. Kernighan, I think), "first make it work, then make it fast" :)
Re: How to redirect printf to QTextEdit?
much thanks stampede, I'll try to implement your solution. Will report back, regards.
Re: How to redirect printf to QTextEdit?
I've been very bussy latelly so couldn't spend much time on Qt. But anyway, the solutions from stampede works with small adjustment.
Code:
stdout = freopen("test.txt","w",stdout);
must change to
Code:
freopen("test.txt","w",stdout);
in my case on Windows and MinGw. Still I have problem when I try to reenable buffering. Here is the relevant part of my sample code
Code:
// redirect stdout to file
freopen("test.txt","w",stdout);
// disable buffering
setvbuf(stdout,NULL,_IONBF,0);
// check if file changed
watcher->addPath("test.txt");
connect(watcher,
SIGNAL(fileChanged
(QString)),
this,
SLOT(HandleFileChange
(QString)));
printf("second print\n");
printf("third print\n");
//library usage come here....
// reenable buffering
setvbuf(stdout,NULL,_IOFBF,0);
//return stdout to display
freopen( "CON","w",stdout);
but I get "Invalid parameter passed to C runtime function" on second setvbuf. Besides there's another issue I'd like to solve. The library has many printf-s when in debug mode, the code looks like this
Code:
#ifdef DEBUG
printf("unable to do...");
#endif
however when I debug it in Qt creator I don't get the prints. It looks like it doesn't recongnize I am in debug mode. Is there something I'm missing? Do I have to adjust MinGw somehow? Much thanks again for your help.
Re: How to redirect printf to QTextEdit?
Quote:
change to freopen("test.txt","w",stdout);
sure, it was a leftover after fclose(); and stdout = fopen(...);
Quote:
It looks like it doesn't recongnize I am in debug mode. Is there something I'm missing?
Is symbol "DEBUG" defined in debug mode ?
Re: How to redirect printf to QTextEdit?
Quote:
Is symbol "DEBUG" defined in debug mode ?
Sorry but don't know how to check/do this. Would you please paste a short snippet of code, or a tutorial reference link? Thanks again.
Re: How to redirect printf to QTextEdit?
for example, you can put this in .pro file:
Code:
build_pass:CONFIG(debug, debug|release) {
DEFINES += <symbols you want to be defined only in debug build>
}
so in your case DEFINES += DEBUG should be ok. Of course, this is all true under assumption that you can rebuild this library when compiling your project.
Re: How to redirect printf to QTextEdit?
Quote:
Originally Posted by
stampede
for example, you can put this in .pro file:
Code:
build_pass:CONFIG(debug, debug|release) {
DEFINES += <symbols you want to be defined only in debug build>
}
so in your case DEFINES += DEBUG should be ok. Of course, this is all true under assumption that you can rebuild this library when compiling your project.
Great, it works :) Now the only problem I have to solve is "Invalid parameter passed to C runtime function" on second setvbuf. If I comment out the code like this
Code:
// redirect stdout to file
freopen("test.txt","w",stdout);
// disable buffering
setvbuf(stdout,NULL,_IONBF,0);
// check if file changed
watcher->addPath("test.txt");
connect(watcher,
SIGNAL(fileChanged
(QString)),
this,
SLOT(HandleFileChange
(QString)));
printf("second print\n");
printf("third print\n");
//library usage come here....
// reenable buffering
//setvbuf(stdout,NULL,_IOFBF,0);
//return stdout to display
//freopen( "CON","w",stdout);
the error disapers, but that is not the solution :( Any suggestion how can I fix this?
Re: How to redirect printf to QTextEdit?
Code:
#include <stdio.h>
int main(){
freopen("test.txt","w",stdout);
setvbuf(stdout,NULL,_IONBF,0);
printf("into the file");
freopen( "CON","w",stdout);
printf("console");
return 0;
}
This works ok on windows, tested with gcc 4.5.2 and 4.7.3. But of course it is not very portable ("CON":)). I didn't try that but on linux maybe you can reopen stdout with "/dev/tty".
Re: How to redirect printf to QTextEdit?
Hi, I've found out that the buffer size 0 causes the problem, so I tried
Code:
setvbuf(stdout,NULL,_IOFBF,4000);
and it doesn't complain any more. However I'd like to set the size of the buffer as it was before my redirection to file. Is there any command that would return the current buffer size and the buffer mode? Much thanks again, regards.
Re: How to redirect printf to QTextEdit?
Code:
setvbuf(stdout,NULL,_IOFBF,4000);
I think you can use BUFSIZ macro instead of 4000.
On linux you could use extra io functions defined in stdio_ext.h to get stream parameters, but I don't know if there exists any win32 port (if you know please post it). Here is a short manual : Controlling buffering.
Why are you concerned about the exact size of the console output buffer ?
Code:
freopen( "CON","w",stdout);
should reopen output stream with default parameters.
This approach can cause some troubles if the stdout was redirected (if you start a program from the console and redirect the stdout via ">"). Example:
Code:
#include <iostream>
#include <stdio.h>
int main(){
std::cout << "std cout 1\n";
freopen("test.txt","w",stdout);
std::cout << "into test.txt\n";
freopen("con","w",stdout);
std::cout << "std cout 2\n";
return 0;
}
If you start this program from the console like "a.exe > test2.txt" then only "std cout 1\n" will be written to test2.txt. "std cout 2\n" will be printed on the console window, as the stdout was reopened with default parameters.
A solution is to duplicate the output stream before redirecting it: dup:
Code:
#include <iostream>
#include <stdio.h>
#include <unistd.h>
int main(){
int std_fd = dup(fileno(stdout));
if (std_fd == -1){
std::cout << "dup failed: " << errno << "\n";
return 0;
}
std::cout << "std cout 1\n";
freopen("test.txt","w",stdout);
std::cout << "into test.txt\n";
fflush(stdout);
if( -1 == dup2(std_fd, fileno(stdout)) ){
return errno;
}
close(std_fd);
std::cout << "std cout 2\n";
return 0;
}
This program will correctly restore the redirected output, because it duplicates the original stdout file descriptor.
Re: How to redirect printf to QTextEdit?
Thanks stampede. I see you know a lot about this stuff, but I don't, at least not yet ;)
Quote:
Why are you concerned about the exact size of the console output buffer ?
Well as I want to redirect the outputs just for the time I'm usging the external open source library in my app. So I thought, if I disable buffering before before library calls, I should also enable them again after I finish using it. But if
Code:
freopen( "CON","w",stdout);
reenables buffering with default parameters, then I obviously don't need some extra commands.
Please help me understand one more thing. Does the "freopen" mean that all commands like (cout, printf,...don't know others yet) which by default output to screen/console, will get redirected to file in my case? I so, that's ok, since I want to intercept all the messages the library spits out.
Quote:
If you start this program from the console like "a.exe > test2.txt" then only "std cout 1\n" will be written to test2.txt. "std cout 2\n" will be printed on the console window, as the stdout was reopened with default parameters.
my app is gui desktiop app, so I don't need to take care of this. But will definitely try the solution with "dup", just for the sake of learning something new. Much thanks again.
Re: How to redirect printf to QTextEdit?
Quote:
Does the "freopen" mean that all commands like (cout, printf,...don't know others yet) which by default output to screen/console, will get redirected to file in my case?
Yes, assuming that this library won't redirect the stdout somewhere else:)