Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    Is there a cross-platform possibility to capture a printf() from stdout (No QProcess)?

    General and Desktop
    3
    11
    5264
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D
      devjb last edited by

      Hi,

      I am writing my first QT Gui Application thus I am not very experienced yet regarding QT.
      I use a standard c library (http://libnodave.sourceforge.net/) in my project to communicate with an industrial controller (PLC).

      In that library are several printf()-Statements which I want to redirect to qdebug() (or use it in some place on the GUI). This has to work on both linux and windows.

      Could anyone help me to find some hints to do that? I tried some code snippets from some old mailing list posts which did not work and I am completely frustrated. The problem first sounded not very complicated but the deeper I look for a solution the more I despair of it.

      I appreciate any hint you could give me.
      Thanks in advance.

      Jochen

      1 Reply Last reply Reply Quote 0
      • B
        Buggy last edited by

        Hi,
        is this of any help to you?
        http://qt-project.org/forums/viewthread/23075

        Regards
        Buggy

        1 Reply Last reply Reply Quote 0
        • B
          Buggy last edited by

          Or hopefully this one fits better (incidentally, it also mentions a guy named Jochen ;)
          http://lists.qt.nokia.com/public/qt-interest/2011-January/030998.html

          Regards
          Buggy

          1 Reply Last reply Reply Quote 0
          • D
            devjb last edited by

            Hi,

            indeed I found that two posting and the first thread seems to be worth a try.
            Unfortunately the link to the code of that guy in the second thread is not working anymore and I did not find

            http://lists.trolltech.com/qt-interest/2005-06/thread00166-0.html

            somewhere else :-(

            1 Reply Last reply Reply Quote 0
            • B
              Buggy last edited by

              Hi,

              here is an "old copy":http://web.archive.org/web/20120109050130/http://lists.trolltech.com/qt-interest/2005-06/thread00166-0.html

              But from my understanding you did not look for a std::string based solution anyway but for the C printf one?

              1 Reply Last reply Reply Quote 0
              • D
                devjb last edited by

                Yes, I just found the old code too in the waybackmachine and tried it in my application noticing that it

                a) seemed to work only on c++ cout
                b) is based on qt3

                Indeed I am searching for a solution for "printf()"

                Regards

                Jochen

                1 Reply Last reply Reply Quote 0
                • D
                  dbzhang800 last edited by

                  Hi, seems what you are looking is:

                  http://stackoverflow.com/questions/5911147/how-to-redirect-printf-output-back-into-code

                  1 Reply Last reply Reply Quote 0
                  • D
                    devjb last edited by

                    Hi, thanks for the hint.
                    That code example might indeed do its work. But as far as I see, I have to execute it somehow cyclic with a timer to do what I want. That does not sound like an elegant way, does it?

                    Regards

                    Jochen

                    1 Reply Last reply Reply Quote 0
                    • D
                      dbzhang800 last edited by

                      [quote author="devjb" date="1372758457"]Hi, thanks for the hint.
                      That code example might indeed do its work. But as far as I see, I have to execute it somehow cyclic with a timer to do what I want. That does not sound like an elegant way, does it?

                      Regards

                      Jochen[/quote]

                      Yes, but you can use select() under posix system and Io Completion Port under windows system to watch the pipe if you want.

                      The source code of QProcess can be used as reference.

                      1 Reply Last reply Reply Quote 0
                      • D
                        dbzhang800 last edited by

                        Hi, FYI, I just implement a new class with asynchronous I/O.

                        https://github.com/dbzhang800/StdoutRedirector

                        Simply create a instance of StdoutRedirector, then watch the readyRead() signal of it.
                        @
                        redirector = new StdoutRedirector(this, StdoutRedirector::StandardOutput|StdoutRedirector::StandardError);
                        connect(redirector, SIGNAL(readyRead()), this, SLOT(...));
                        @

                        When data exists, read() can be used to get the data.
                        @
                        QByteArray StdoutRedirector::read(qint64 maxlen)
                        @

                        1 Reply Last reply Reply Quote 0
                        • D
                          devjb last edited by

                          Thank you,

                          nice solution.

                          I just finished a solution for me on my own yesterday, based on the above-mentioned stackoverflow post. It catches every stdout output and throws it on the debug console as well as in a widget on the main window.

                          Regards

                          Jochen

                          main.cpp:
                          @//configure stdout to autoflush (seems it needs slight changes on win)
                          setvbuf(stdout, NULL, _IONBF, 0);@

                          stdoutredirector.h:
                          @#ifndef STDOUTREDIRECTOR_H
                          #define STDOUTREDIRECTOR_H
                          #include <QObject>
                          #include <QThread>
                          #include <QDebug>
                          #include <QMainWindow>
                          #include <fcntl.h>
                          #include <stdlib.h>
                          #include <stdio.h>
                          /* gcc defined unix */
                          #ifdef LINUX
                          #include <unistd.h>
                          #endif
                          #ifdef BCCWIN
                          #include <io.h>
                          #define pipe(X) _pipe(X,4096,O_BINARY)
                          #define fileno _fileno
                          #define dup2 _dup2
                          #define read _read

                          #endif
                          #include <assert.h>

                          class stdoutRedirector : public QThread
                          {
                          Q_OBJECT
                          public:

                          stdoutRedirector();
                          ~stdoutRedirector();
                          void run();
                          

                          signals:
                          void writeOut(QString);
                          public slots:
                          void terminate();

                          private:

                          int fds[2];
                          int res;
                          char buf[256];
                          int so;
                          bool terminate_;
                          

                          };

                          #endif // STDOUTREDIRECTOR_H@

                          logtoparent.h:

                          @#ifndef LOGTOPARENT_H
                          #define LOGTOPARENT_H
                          #include "mainwindow.h"
                          #include <QMainWindow>
                          #include <QString>

                          class logToParent : public QMainWindow
                          {
                          Q_OBJECT
                          public:
                          explicit logToParent(MainWindow *parent = 0);
                          ~logToParent();
                          QStatusBar *parentStatbar;
                          signals:
                          void threadTerminator();
                          public slots:

                          void updateParentLog(QString logString);
                          

                          };

                          #endif // LOGTOPARENT_H@

                          logtoparent.cpp:

                          @#include "logtoparent.h"
                          using namespace std;

                          logToParent::logToParent(MainWindow *parent) :
                          QMainWindow(parent)
                          {
                          stdoutRedirector * myRedirector = new stdoutRedirector;
                          connect(this, SIGNAL(threadTerminator()),myRedirector,SLOT(terminate()));
                          cout << "Debug: Qthread for logging run: " << myRedirector->isRunning() << endl;
                          myRedirector->start();
                          cout << "Debug: Logger constructed" << endl;
                          cout << "Debug: Qthread for logging run: " << myRedirector->isRunning() << endl;
                          parentStatbar = parent->ui->statusBar;
                          connect(myRedirector, SIGNAL(writeOut(QString)),this,SLOT(updateParentLog(QString)));
                          }

                          logToParent::~logToParent()
                          {
                          emit threadTerminator();
                          }

                          void logToParent::updateParentLog(QString logString)
                          {
                          parentStatbar->showMessage(logString,2500);

                          }@

                          stdoutredirector.cpp:
                          @#include "stdoutredirector.h"

                          stdoutRedirector::stdoutRedirector()
                          {
                          res=pipe(fds);
                          assert(res==0);

                          so=fileno(stdout);
                          // close stdout handle and make the writable part of fds the new stdout.
                          res=dup2(fds[1],so);
                          assert(res!=-1);
                          terminate_ = false;
                          

                          }

                          stdoutRedirector::~stdoutRedirector()
                          {

                          }

                          void stdoutRedirector::run()
                          {

                          Q_FOREVER{
                          res=read(fds[0],buf,sizeof(buf)-1);
                          assert(res>=0 && res<sizeof(buf));
                          buf[res]=0;
                          emit writeOut(buf);
                          qDebug() << buf;
                          //fprintf(stderr,"printf: %s\n",buf);
                          if (terminate_)
                          {
                              return;
                          }
                          }
                          

                          }
                          void stdoutRedirector::terminate()
                          {
                          terminate_ = true;
                          }
                          @

                          and finally, in main window's constructor:
                          @logToParent* logger = new logToParent(this);@

                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post