Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Is there a cross-platform possibility to capture a printf() from stdout (No QProcess)?
QtWS25 Last Chance

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

Scheduled Pinned Locked Moved General and Desktop
11 Posts 3 Posters 5.8k Views
  • 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 Offline
    D Offline
    devjb
    wrote on last edited by
    #1

    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
    0
    • B Offline
      B Offline
      Buggy
      wrote on last edited by
      #2

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

      Regards
      Buggy

      1 Reply Last reply
      0
      • B Offline
        B Offline
        Buggy
        wrote on last edited by
        #3

        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
        0
        • D Offline
          D Offline
          devjb
          wrote on last edited by
          #4

          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
          0
          • B Offline
            B Offline
            Buggy
            wrote on last edited by
            #5

            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
            0
            • D Offline
              D Offline
              devjb
              wrote on last edited by
              #6

              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
              0
              • D Offline
                D Offline
                dbzhang800
                wrote on last edited by
                #7

                Hi, seems what you are looking is:

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

                1 Reply Last reply
                0
                • D Offline
                  D Offline
                  devjb
                  wrote on last edited by
                  #8

                  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
                  0
                  • D Offline
                    D Offline
                    dbzhang800
                    wrote on last edited by
                    #9

                    [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
                    0
                    • D Offline
                      D Offline
                      dbzhang800
                      wrote on last edited by
                      #10

                      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
                      0
                      • D Offline
                        D Offline
                        devjb
                        wrote on last edited by
                        #11

                        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
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved