Results 1 to 13 of 13

Thread: How to redirect printf to QTextEdit?

  1. #1
    Join Date
    Oct 2013
    Posts
    102
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default 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.
    Last edited by arcull; 7th November 2013 at 10:14.

  2. #2
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default 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):
    Qt Code:
    1. // widget.h
    2. include <QPushButton>
    3. #include <QFileSystemWatcher>
    4. #include <QMessageBox>
    5. #include <cstdio>
    6.  
    7. class Widget : public QWidget{
    8. Q_OBJECT
    9. public:
    10. explicit Widget(const QString& fileName, QWidget * parent = NULL)
    11. :QWidget(parent)
    12. ,_nBytes(0)
    13. {
    14. QPushButton * btn = new QPushButton("add text", this);
    15. connect(btn, SIGNAL(clicked()), this, SLOT(onClick()));
    16. QFileSystemWatcher * watcher = new QFileSystemWatcher(this);
    17. watcher->addPath(fileName);
    18. connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(fileChanged(QString)));
    19. }
    20. private slots:
    21. void onClick(){
    22. static int counter = 0;
    23. printf("text (%i)",counter++);
    24. }
    25. void fileChanged(const QString& path){
    26. QFile f(path);
    27. if( f.open(QIODevice::ReadOnly) ){
    28. f.seek(_nBytes);
    29. const QByteArray ba = f.readAll();
    30. _nBytes += ba.size();
    31. QMessageBox::information(this,"stdout",path + " changed:\n\n" + ba);
    32. } else {
    33. QMessageBox::critical(this,"stdout","can't open!");
    34. }
    35. }
    36. private:
    37. int _nBytes;
    38.  
    39. };
    40.  
    41. #endif
    42.  
    43. // main.cpp
    44. #include <QApplication>
    45. #include <cstdio>
    46.  
    47. #include "widget.h"
    48.  
    49. int main(int argc, char ** argv){
    50. stdout = freopen("test.txt","w",stdout);
    51. setvbuf(stdout, NULL, _IONBF, 0);
    52. QApplication app(argc,argv);
    53. Widget w("test.txt");
    54. w.show();
    55. return app.exec();
    56. }
    To copy to clipboard, switch view to plain text mode 

    As my first programming teacher always said (quoting B. Kernighan, I think), "first make it work, then make it fast"
    Last edited by stampede; 7th November 2013 at 19:15.

  3. #3
    Join Date
    Oct 2013
    Posts
    102
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to redirect printf to QTextEdit?

    much thanks stampede, I'll try to implement your solution. Will report back, regards.

  4. #4
    Join Date
    Oct 2013
    Posts
    102
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default 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.
    Qt Code:
    1. stdout = freopen("test.txt","w",stdout);
    To copy to clipboard, switch view to plain text mode 
    must change to
    Qt Code:
    1. freopen("test.txt","w",stdout);
    To copy to clipboard, switch view to plain text mode 
    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
    Qt Code:
    1. // redirect stdout to file
    2. freopen("test.txt","w",stdout);
    3.  
    4. // disable buffering
    5. setvbuf(stdout,NULL,_IONBF,0);
    6.  
    7. // check if file changed
    8. QFileSystemWatcher * watcher = new QFileSystemWatcher(this);
    9. watcher->addPath("test.txt");
    10. connect(watcher,SIGNAL(fileChanged(QString)),this,SLOT(HandleFileChange(QString)));
    11.  
    12. printf("second print\n");
    13.  
    14. printf("third print\n");
    15.  
    16. //library usage come here....
    17.  
    18. // reenable buffering
    19. setvbuf(stdout,NULL,_IOFBF,0);
    20.  
    21. //return stdout to display
    22. freopen( "CON","w",stdout);
    To copy to clipboard, switch view to plain text mode 
    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
    Qt Code:
    1. #ifdef DEBUG
    2. printf("unable to do...");
    3. #endif
    To copy to clipboard, switch view to plain text mode 
    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.

  5. #5
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: How to redirect printf to QTextEdit?

    change to freopen("test.txt","w",stdout);
    sure, it was a leftover after fclose(); and stdout = fopen(...);
    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 ?

  6. #6
    Join Date
    Oct 2013
    Posts
    102
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to redirect printf to QTextEdit?

    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.

  7. #7
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: How to redirect printf to QTextEdit?

    for example, you can put this in .pro file:
    Qt Code:
    1. build_pass:CONFIG(debug, debug|release) {
    2. DEFINES += <symbols you want to be defined only in debug build>
    3. }
    To copy to clipboard, switch view to plain text mode 
    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.

  8. #8
    Join Date
    Oct 2013
    Posts
    102
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to redirect printf to QTextEdit?

    Quote Originally Posted by stampede View Post
    for example, you can put this in .pro file:
    Qt Code:
    1. build_pass:CONFIG(debug, debug|release) {
    2. DEFINES += <symbols you want to be defined only in debug build>
    3. }
    To copy to clipboard, switch view to plain text mode 
    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
    Qt Code:
    1. // redirect stdout to file
    2. freopen("test.txt","w",stdout);
    3.  
    4. // disable buffering
    5. setvbuf(stdout,NULL,_IONBF,0);
    6.  
    7. // check if file changed
    8. QFileSystemWatcher * watcher = new QFileSystemWatcher(this);
    9. watcher->addPath("test.txt");
    10. connect(watcher,SIGNAL(fileChanged(QString)),this,SLOT(HandleFileChange(QString)));
    11.  
    12. printf("second print\n");
    13.  
    14. printf("third print\n");
    15.  
    16. //library usage come here....
    17.  
    18. // reenable buffering
    19. //setvbuf(stdout,NULL,_IOFBF,0);
    20.  
    21. //return stdout to display
    22. //freopen( "CON","w",stdout);
    To copy to clipboard, switch view to plain text mode 
    the error disapers, but that is not the solution Any suggestion how can I fix this?

  9. #9
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: How to redirect printf to QTextEdit?

    Qt Code:
    1. #include <stdio.h>
    2.  
    3. int main(){
    4. freopen("test.txt","w",stdout);
    5. setvbuf(stdout,NULL,_IONBF,0);
    6. printf("into the file");
    7. freopen( "CON","w",stdout);
    8. printf("console");
    9. return 0;
    10. }
    To copy to clipboard, switch view to plain text mode 
    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".

  10. #10
    Join Date
    Oct 2013
    Posts
    102
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: How to redirect printf to QTextEdit?

    Hi, I've found out that the buffer size 0 causes the problem, so I tried
    Qt Code:
    1. setvbuf(stdout,NULL,_IOFBF,4000);
    To copy to clipboard, switch view to plain text mode 
    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.

  11. #11
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: How to redirect printf to QTextEdit?

    Qt Code:
    1. setvbuf(stdout,NULL,_IOFBF,4000);
    To copy to clipboard, switch view to plain text mode 
    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 ?
    Qt Code:
    1. freopen( "CON","w",stdout);
    To copy to clipboard, switch view to plain text mode 
    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:
    Qt Code:
    1. #include <iostream>
    2. #include <stdio.h>
    3.  
    4. int main(){
    5. std::cout << "std cout 1\n";
    6. freopen("test.txt","w",stdout);
    7. std::cout << "into test.txt\n";
    8. freopen("con","w",stdout);
    9. std::cout << "std cout 2\n";
    10. return 0;
    11. }
    To copy to clipboard, switch view to plain text mode 
    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:
    Qt Code:
    1. #include <iostream>
    2. #include <stdio.h>
    3. #include <unistd.h>
    4.  
    5. int main(){
    6. int std_fd = dup(fileno(stdout));
    7. if (std_fd == -1){
    8. std::cout << "dup failed: " << errno << "\n";
    9. return 0;
    10. }
    11.  
    12. std::cout << "std cout 1\n";
    13.  
    14. freopen("test.txt","w",stdout);
    15. std::cout << "into test.txt\n";
    16.  
    17. fflush(stdout);
    18. if( -1 == dup2(std_fd, fileno(stdout)) ){
    19. return errno;
    20. }
    21. close(std_fd);
    22. std::cout << "std cout 2\n";
    23.  
    24. return 0;
    25. }
    To copy to clipboard, switch view to plain text mode 
    This program will correctly restore the redirected output, because it duplicates the original stdout file descriptor.

  12. #12
    Join Date
    Oct 2013
    Posts
    102
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default 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
    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
    Qt Code:
    1. freopen( "CON","w",stdout);
    To copy to clipboard, switch view to plain text mode 
    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.
    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.

  13. #13
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: How to redirect printf to QTextEdit?

    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

Similar Threads

  1. Redirect key strokes
    By iPick12 in forum Qt Programming
    Replies: 1
    Last Post: 11th September 2012, 16:55
  2. How to redirect to a URL in Qt
    By xyz in forum Newbie
    Replies: 8
    Last Post: 30th March 2012, 07:39
  3. redirect qDebug() to file
    By sriky27 in forum Qt Programming
    Replies: 9
    Last Post: 17th March 2009, 20:21
  4. Replies: 4
    Last Post: 27th March 2008, 09:21
  5. Redirect printf to QTextEdit?
    By Randulf in forum Qt Programming
    Replies: 9
    Last Post: 12th October 2006, 14:57

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.