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. [SOLVED]Qt capture stdout
Forum Update on Monday, May 27th 2025

[SOLVED]Qt capture stdout

Scheduled Pinned Locked Moved General and Desktop
18 Posts 5 Posters 35.4k 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.
  • J Offline
    J Offline
    Jake007
    wrote on 26 Dec 2012, 16:56 last edited by
    #1

    Hi!

    In my current project, I need to get stdout into a custom reader. Everything works as expected in sample project ( no Qt), and in project were program is run directly from Qt Creator.
    But as soon as a program is started directly from .exe, custom stream reader fails to bind to stdout, because Qt binds to it.

    1. How can I prevent Qt from binding stdout?
    2. If I can't, can I bind first so that Qt will fail? Will this crash Qt app?
    3. Qt Creator probably starts a program with some parameters to prevent this, so that my reader works. What are those parameters? Note: With qDebug << argc; I get 1, so that means only program executable path. How Qt Creator starts the program?

    Note: I cannot solve my problem with QProcess.

    Regards,
    Jake


    Code is poetry

    1 Reply Last reply
    0
    • M Offline
      M Offline
      MuldeR
      wrote on 26 Dec 2012, 17:39 last edited by
      #2

      I don't quite understand your problem yet.

      If you "capture" the STDOUT (or STDERR), there must be two processes involved:

      • The process that writes something to its STDOUT/STDERR
      • The process that tries to capture the STDOUT/STDERR of the other process

      And this can be done in (at least) two different ways:

      • Create both processes in a way that the STDOUT (or STDERR) of the first process is connected to the STDIN of the second one (e.g. from the Shell, using the "pipe" operator). Then just read from STDIN.
      • Let the first process create the second one as its child-process and then let it read from the child process' STDOUT or STDERR handle (typically this is done using QProcess or via Win32 API)

      What exactly are you doing? Which of two processes is based on Qt? And which of them is failing?

      My OpenSource software at: http://muldersoft.com/

      Qt v4.8.6 MSVC 2013, static/shared: http://goo.gl/BXqhrS

      Go visit the coop: http://youtu.be/Jay...

      1 Reply Last reply
      0
      • J Offline
        J Offline
        Jake007
        wrote on 26 Dec 2012, 17:58 last edited by
        #3

        Everything is in the same process ( one Qt app).
        I need to redirect outputs of a interpreter which is built with a program (necessary, otherwise I do not have enough control over it). It's output is equivalent to printf. I've been doing this with a help of "this":http://stackoverflow.com/a/5419409 class.

        Bellow executes return, which means that it cannot bind to STDOUT nor to STDERR:
        @if (m_oldStdOut == -1 || m_oldStdErr == -1)
        return;@


        Code is poetry

        1 Reply Last reply
        0
        • M Offline
          M Offline
          master of disaster
          wrote on 26 Dec 2012, 18:03 last edited by
          #4

          If you want to redirect stdout, this code should work:

          @
          stdout = freopen("output_file", "w", stdout);
          @

          You'll need the C header stdio.h.

          1 Reply Last reply
          0
          • J Offline
            J Offline
            Jake007
            wrote on 26 Dec 2012, 18:05 last edited by
            #5

            This outputs it into a file, but I need it in QString, string or char * variable.


            Code is poetry

            1 Reply Last reply
            0
            • M Offline
              M Offline
              master of disaster
              wrote on 26 Dec 2012, 18:10 last edited by
              #6

              Try this:

              @
              stdout = freopen("output_file", "w", stdout);
              ...
              QFile f;
              f.open("output_file", QIODevice::ReadOnly);
              QByteArray output = f.readAll();
              QString out(output);
              @

              A bit complicated, but it works (hopefully).

              1 Reply Last reply
              0
              • J Offline
                J Offline
                Jake007
                wrote on 26 Dec 2012, 18:13 last edited by
                #7

                I'd work. But the problem is, that working with disk and files is a huge performance drop. Imagine you need to read it 10 000 times per second.
                If it would do up to 100 times per second, I'd be happy.


                Code is poetry

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  master of disaster
                  wrote on 26 Dec 2012, 18:27 last edited by
                  #8

                  Well, then you could try some other hacking, but I'm not sure if it will work.

                  @
                  fpos_t pos;

                  fgetpos(stdout, &pos);
                  @

                  Now you have the current position of the text cursor (the beginning of the following output). Then you run the program.

                  Now it's time to get the output. We reset the position to the position where the output starts and then read everything to the end:

                  @
                  FILE *f = stdout;
                  fsetpos(f, &pos);

                  QFile file(f);
                  QByteArray output = file.readAll();
                  @

                  Some weird code, but it might even work...

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    MuldeR
                    wrote on 26 Dec 2012, 18:37 last edited by
                    #9

                    Don't know if you can do that with Qt only, but with the Win32 API this should work:

                    @#include <stdio.h>
                    #include <io.h>
                    #include <fcntl.h>
                    #include <Windows.h>

                    //Create a new pipe
                    HANDLE hRead;
                    HANDLE hWrite;
                    if(!CreatePipe(&hRead, &hWrite, NULL, NULL))
                    {
                    fprintf(stderr, "FATAL: CreatePipe failed !!!\n");
                    _exit(42);
                    }

                    //Get C-style FILE* pointers from OS handles
                    int iReadDescr = _open_osfhandle((intptr_t) hRead, _O_RDONLY|_O_BINARY);
                    int iWriteDescr = _open_osfhandle((intptr_t) hWrite, _O_WRONLY|_O_BINARY);
                    FILE *fRead = (iReadDescr >= 0) ? _fdopen(iReadDescr, "rb") : NULL;
                    FILE *fWrite = (iWriteDescr >= 0) ? _fdopen(iWriteDescr, "wb") : NULL;

                    //Set stdout and stderr
                    *stdout = *fWrite;
                    *stderr = *fWrite;

                    /* --- the following is for test only --- */

                    //Create some test output on stdout
                    printf("Hallo Welt!");
                    fflush(stdout); //Don't forget to flush or the fread() below will hang forever !!!

                    //Get output from pipe (use DbgView to display!)
                    for(;;)
                    {
                    char buff[2] = {'\0', '\0'};
                    int len = fread(buff, sizeof(char), 1, fRead);
                    if(len > 0) OutputDebugStringA(buff);
                    }@

                    Better solution, of course, would be to modify the code of your "interpreter" to NOT using printf(), but using fprintf() instead with a user-defined stream (can be set via some API and may still default to stdout). Or even better: Use a user-defined logging function (can be set via some API and may still default to printf).

                    My OpenSource software at: http://muldersoft.com/

                    Qt v4.8.6 MSVC 2013, static/shared: http://goo.gl/BXqhrS

                    Go visit the coop: http://youtu.be/Jay...

                    1 Reply Last reply
                    0
                    • J Offline
                      J Offline
                      Jake007
                      wrote on 26 Dec 2012, 19:01 last edited by
                      #10

                      master of disaster
                      Thanks for your effort. Code is weird indeed, but unfortunately not working. I tried using the following code:

                      @printf("aaaaaaaaaaaa"); // Also tried moving it after stdout is open with QFile

                      QFile file;
                      file.open(stdout, QIODevice::ReadOnly);

                      QFile result("result.txt");
                      result.open(QIODevice::WriteOnly | QIODevice::Text);

                      QTextStream txtStream(&result);
                      txtStream << file.readAll(); // I get around 200 lines of NUL code in notepad++

                      result.close();
                      file.close();@

                      MuldeR
                      Thanks. I'll try your code, but if will work, It'll be a temporary solutions, as the program is meant to be cross platform (desktop OSs).
                      Do you maybe know how Qt Creator starts the app? In worst case, I could start it the same way ( but I assume I might get performance decrease).

                      I'll also take a look at option of modifying the interpreter and writing user-defined a stream.


                      Code is poetry

                      1 Reply Last reply
                      0
                      • M Offline
                        M Offline
                        MuldeR
                        wrote on 26 Dec 2012, 19:05 last edited by
                        #11

                        If it can not be done with Qt entirely, you may need to write platform-specific code for each OS.

                        ...or do it properly and modify the "interpreter" code to set a user-define logging function (should be the best).

                        Note that I have just update the code that I posted above a bit!

                        My OpenSource software at: http://muldersoft.com/

                        Qt v4.8.6 MSVC 2013, static/shared: http://goo.gl/BXqhrS

                        Go visit the coop: http://youtu.be/Jay...

                        1 Reply Last reply
                        0
                        • J Offline
                          J Offline
                          Jake007
                          wrote on 26 Dec 2012, 19:20 last edited by
                          #12

                          If I run it from Qt Creator works as it should. That class from stackoverflow works without any problems. So I'm not wiling to give up just yet.

                          Otherwise I'll have no other option than modifying interpreters source code.


                          Code is poetry

                          1 Reply Last reply
                          0
                          • M Offline
                            M Offline
                            MuldeR
                            wrote on 26 Dec 2012, 19:21 last edited by
                            #13

                            And if you don't want your fread() to block until there's new data to read, use a separate thread:

                            @void reader_func(void *handle)
                            {
                            char line[2048];
                            size_t linepos = 0;

                            //Read output and process (use DbgView to display!)
                            for(;;)
                            {
                                //Read next char
                                char buff;
                                int len = fread(&buff, sizeof(char), 1, *((FILE**)handle));
                            
                                //If successfull, append to line buffer
                                if(len == 1)
                                {
                                    line[linepos++] = buff;
                            
                                    //If end of line, do output & reset
                                    if(buff == '\r' || buff == '\n' || buff == '\b')
                                    {
                                        if(linepos > 1)
                                        {
                                            line[linepos-1] = '\n';  //Set last char to line-break
                                            line[linepos++] = '\0';  //Append NULL terminator
                                            OutputDebugStringA(line);
                                        }
                                        linepos = 0;
                                    }
                                }
                            }
                            

                            }

                            int main(...)
                            {
                            //Setup stdout/stderr as shown before
                            /* ... */

                            //Start reader thread
                            _beginthread(reader_func, 0, &fRead);
                            
                            //Create some test output on stdout
                            printf("Hallo Welt!\n");
                            fflush(stdout); //Don't forget to flush !!!
                            Sleep(5000);
                            printf("Tschüss!\n");
                            fflush(stdout); //Don't forget to flush !!!
                            Sleep(1000);
                            

                            }@

                            My OpenSource software at: http://muldersoft.com/

                            Qt v4.8.6 MSVC 2013, static/shared: http://goo.gl/BXqhrS

                            Go visit the coop: http://youtu.be/Jay...

                            1 Reply Last reply
                            0
                            • J Offline
                              J Offline
                              Jake007
                              wrote on 27 Dec 2012, 10:46 last edited by
                              #14

                              After further tests, I found out, that stdout already starts closed with a program run as standalone. I did not found a solution (platform independent) to reopen it.

                              I'll go with a solution of modifying source code of the interpreter -> printf to fprintf as you recommended (done). For opening stream into memory instead into a file I planed to use fmemopen. But after after making a test project of use a fmemopen function ( code from "here":http://pubs.opengroup.org/onlinepubs/9699919799/functions/fmemopen.html), I get an error that fmemopen was not declared.
                              After further searching I did not find any other useful with same functionality. Is there an alternative function or a different way?


                              Code is poetry

                              1 Reply Last reply
                              0
                              • M Offline
                                M Offline
                                MuldeR
                                wrote on 27 Dec 2012, 15:57 last edited by
                                #15

                                I don't think fmemopen() is a standard C/C++ function. It's probably not portable!

                                Well, I already gave you some code that creates a Pipe and gives you C-style FILE* pointers to it.

                                That code is for Win32 only though. You need to figure out an implementation for Unix/Linux.

                                But: If you modify the code anyway, why not have your "interpreter" take a logging function as parameter?

                                You could pass a function pointer to a user-defined function, so you won't even need a stream.

                                And, as we are on the Qt forums here, why not use Signals & Slots ???

                                You could give your "interpreter" class a lineLogged(QString &) Signal that will be emitted to log some line.

                                The "main" program would simply connect to that signal and process the output in a suitable Slot function.

                                My OpenSource software at: http://muldersoft.com/

                                Qt v4.8.6 MSVC 2013, static/shared: http://goo.gl/BXqhrS

                                Go visit the coop: http://youtu.be/Jay...

                                1 Reply Last reply
                                0
                                • J Offline
                                  J Offline
                                  Jake007
                                  wrote on 27 Dec 2012, 18:10 last edited by
                                  #16

                                  I figured that out after further searching through the web.
                                  I wanted to stay with streams, because rest of the program is already bound to that chunk of code. Now I'll have to do a few changes ( 10 lines of code is 10 lines of code ;) ).
                                  Interpreter is written in pure C ( not my work, external library), so implementing signals and slots wouldn't be so easy. Replacing all printfs is already pain in the ...
                                  I decided to change print function of the interpreter, so that it will save output to a variable from which I'll later read.

                                  Thanks for all the help!

                                  Marked as solved.

                                  Regards,
                                  Jake


                                  Code is poetry

                                  1 Reply Last reply
                                  0
                                  • osirisgothraO Offline
                                    osirisgothraO Offline
                                    osirisgothra
                                    wrote on 7 Nov 2013, 09:10 last edited by
                                    #17

                                    [quote author="Jake007" date="1356631812"]I figured that out after further searching through the web.
                                    I wanted to stay with streams, because rest of the program is already bound to that chunk of code. Now I'll have to do a few changes ( 10 lines of code is 10 lines of code ;) ).
                                    Interpreter is written in pure C ( not my work, external library), so implementing signals and slots wouldn't be so easy. Replacing all printfs is already pain in the ...
                                    I decided to change print function of the interpreter, so that it will save output to a variable from which I'll later read.

                                    Thanks for all the help!

                                    Marked as solved.

                                    Regards,
                                    Jake [/quote]

                                    I just wanted you to know that your work here was not in vain, I have the EXACT same problem, and the posts here have helped solve my problem as well, so thanks. (replacing stream with memory stream, replacing printf with fprintf)

                                    I'm truly glad you r/offmychess t finally, but please don't go too far, because you r/beyondvoxels and that implies that u r/donewithlife. Oh well time to git back to the lab, because azure sea here, I have a lot of work to do...

                                    1 Reply Last reply
                                    0
                                    • McLionM Offline
                                      McLionM Offline
                                      McLion
                                      wrote on 26 Mar 2014, 13:38 last edited by
                                      #18

                                      I seem to have the exact same problem as well, posted just "here":http://qt-project.org/forums/viewthread/40286/.
                                      However, I am not quite sure which changes exactly I have to do.
                                      Would you mind recap shortly?
                                      Thanks
                                      McL

                                      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