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



  • 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



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

    Regards
    Buggy



  • 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



  • 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 :-(



  • 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?



  • 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





  • 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 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.



  • 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)
    @



  • 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);@


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.