PDA

View Full Version : Accessing program's own stdout/stderr



TemporalBeing
28th August 2009, 22:25
I have a program where I am porting some old DOS code, and wrapping it in a Qt application.
The problem I have is that the DOS code makes extensive use of writing to stdout and stderr for its data, and I want to capture it all and put it into a QTextEdit.

I've noticed there is some functionality for this kind of thing _when_ running a child process via QProcess.

I came across a couple suggestions, but they are relatively old - one referred to KProcess, but that was a 1998 post (http://lists.trolltech.com/qt-interest/1998-05/msg00140.html), and the second suggested using QSocketNotifier (http://lists.trolltech.com/qt-interest/2002-01/thread00197-0.html) somehow.

I tried using the QSocketNotifier, but I never get any notices even though I know data has been written via printf(). Here's how I setup the access:



if (stdErrorReader == NULL)
{
stdErrorReader = new QFile(this);
if (stdErrorReader != NULL)
{
stdErrorReader->open(2,QIODevice::ReadOnly|QIODevice::Text);
connect(stdErrorReader,SIGNAL(readyRead()),this,SL OT(stdErrorDataAvailable()));
if (stdErrorNotifier == NULL)
{
stdErrorNotifier = new QSocketNotifier(2,QSocketNotifier::Read,this);
if (stdErrorNotifier != NULL)
{
connect(stdErrorNotifier,SIGNAL(activated(int)),th is,SLOT(stdErrorDataAvailable(int)));
}
}
}
}
if (stdOutReader == NULL)
{
stdOutReader = new QFile(this);
if (stdOutReader != NULL)
{
stdOutReader->open(1,QIODevice::ReadOnly|QIODevice::Text);
connect(stdOutReader,SIGNAL(readyRead()),this,SLOT (stdOutDataAvailable()));
if (stdOutNotifier == NULL)
{
stdOutNotifier = new QSocketNotifier(1,QSocketNotifier::Read,this);
if (stdOutNotifier != NULL)
{
connect(stdOutNotifier,SIGNAL(activated(int)),this ,SLOT(stdOutDataAvailable(int)));
}
}
}
}


The 'stdOutDataAvailable(int)' and 'stdOutDataAvailable()' slots never get called.

What am I doing wrong?


Is there a way to access the Application's QProcess() class so that I can use the methodology via QProcess?

nish
29th August 2009, 02:54
whats the problem in using
QProcess::readAllStandardError()

QProcess::readAllStandardOutput()

QProcess::readChannel()

caduel
29th August 2009, 06:53
have you checked that the open calls don't fail?

you can also close stdout and stderr and open a regular file (for that filedescriptor) and just display that file's contents (see the manpages on close, dup etc).

HTH

TemporalBeing
31st August 2009, 14:18
whats the problem in using
QProcess::readAllStandardError()

QProcess::readAllStandardOutput()

QProcess::readChannel()
Please note my original post - I would love to use those functions, but have not figured out how to access the main program's process object. Thus my question...

Note - those functions are not static functions. Thus you need an instance of QProcess() associated with the process you want to read from. How do I get that for the main program? Where's the interface to get it via QApplication or QCoreApplication?

wysota
31st August 2009, 14:31
If you write to your own stdout (as I assume the application does), you can't read it back in. You have to substitute stdout and stderr with some mechanisms that will redirect the data elsewhere. Otherwise you have to modify all calls to printf() and fprintf() in the original code to send the data to some other place. You should be able to simply undef printf and define a new function or macro with this name and then rebuild the application.

TemporalBeing
31st August 2009, 15:44
have you checked that the open calls don't fail?

you can also close stdout and stderr and open a regular file (for that filedescriptor) and just display that file's contents (see the manpages on close, dup etc).

HTH
Yes, I verified - the QFile::Open(int, OpenMode) call is returning 'true' for both stderr, and stdout.

I haven't tried closing stderr/stdout and putting new files in their place - I've done it before, I was just hoping not to here.

I am, however, trying to support Windows in this as well (my primary test environment right now). I may try moving it to Linux and testing to see if that changes things at all as well.

TemporalBeing
31st August 2009, 23:31
Thanks for the tip on stderr/stdout. Never came across that before, but I haven't tried to port legacy code this way before either.

Well, for various reasons I can't get it to work on Linux well enough to even compile (legacy code issues).

I did try replacing stderr, stdout but that didn't work either. (And I've done that in the past and had it work too, but not under Qt.)

So I finally broke down and replaced all the printf/fprintf(stderr) calls with a new function that converts the stuff to QString, and then calls qDebug(), which is then captured via a handler to be redirected to the GUI location I want it to go.

Problem is that the _vsnprintf() in VS2008/Qt4.5.1 seems to be borked - it never prints the text to the buffer, despite having a 32k buffer and data that is no where near 32k in size (likely 80 characters in size at most). It does set the buffer to all spaces, with proper termination; but no data.

I originally pulled some code I had written to add 'printf()' style formatting to the std::string class that managed some dynamic memory to do the conversion with _vsnprintf(), but it just kept allocating memory and never actually writing anything. (And I know the function worked when I wrote and tested it!)

So needless to say, I have to go on to other things for now, but I really want to resolve this issue - and I'm just plain out of ideas right now.

wysota
31st August 2009, 23:47
Can't you undef _vsnprintf() and replace it with your own routine? At worst just reassign the function pointer to something else, it should be doable.

TemporalBeing
1st September 2009, 02:45
And that would require writing something to interpret the whole printf format strings, which I'd rather not do - not to mention, I don't have time for it. vsnprintf/_vsnprintf are great functions, and there's no reason they should be failing like this. Not sure what I'm going to do about it though...