how to pipe qprocess' stdout to father process as stdin



  • I found a methed of QProcess named setStandardOutputProcessalt text
    But I want my QProcess pipe it stdout to father process, How can I do that?


  • Moderators

    @Isolde Is it really needed to do this at runtime? If not then you can just start your app like this:

    my_app | some_other_app
    


  • @jsulm Of course it works! But i think its a little bit inconvenient, so I want a runtime way to do that.



  • @Isolde

    But I want my QProcess pipe it stdout to father process, How can I do that?

    What do you mean by this, what are you trying to do?

    • If you want to pipe to a child process from your program, you create the child via QProcess and use setStandardOutputProcess, as shown in the example.

    • If by "father" process you mean the parent process to your program (e.g. the "shell" from which it is launched) then you can't --- child cannot change parent's file descriptors, it's up to the parent process to decide what to do with the child's stdout at the time it creates it, in effect the shell parent already has child's stdout to do with it as it pleases.


  • Moderators

    @JNBarchan I guess the question here is: what do you pass to setStandardOutputProcess? You would need a QProcess instance for your own process.



  • @jsulm
    I still don't understand the question/objective, you seem to more then I do. Does "father process" mean "self process"? The way you phrase it, do you/OP mean "pipe a process's own stdout to its own stdin"?? Can you explain "clearly", then I might understand?


  • Moderators

    @JNBarchan Original question: "But I want my QProcess pipe it stdout to father process, How can I do that?"
    So, the Qt app shall pass its stdout to stdin from another process (if I understood the question from @Isolde correctly as the question isn't formulated clearly).
    So how would you do this:

    QProcess process2;
    process2.setStandardOutputProcess(/* What to pass here? */);
    process2.start("command2");
    

  • Moderators

    @JNBarchan said in how to pipe qprocess' stdout to father process as stdin:

    father process

    I guess it is a typo and means "further process", but I may be wrong...



  • @jsulm said in how to pipe qprocess' stdout to father process as stdin:

    @JNBarchan Original question: "But I want my QProcess pipe it stdout to father process, How can I do that?"
    So, the Qt app shall pass its stdout to stdin from another process (if I understood the question from @Isolde correctly as the question isn't formulated clearly).
    So how would you do this:

    QProcess process2;
    process2.setStandardOutputProcess(/* What to pass here? */);
    process2.start("command2");
    

    OK, so, the objective is:

    1. Start a child process.
    2. Temporarily redirect self/parent process's stdout to child's stdin.
    3. Produce some stdout from self/parent, to be read by child.
    4. Wait for child to terminate, or stdout to be closed to mark end of output(?) causing child to terminate.
    5. Un-redirect self/parent process's stdout back to whereber it was previously in self/parent.

    Maybe #2 & #5 are not to be "temporary", the whole of parent's output is to be sent to child, there's no need to "temporarily redirect & un-redirect", I don't know?

    I think that's it?


  • Moderators

    @JNBarchan This is my understanding. It is often hard to understand questions and problem descriptions here :-)



  • @jsulm
    LOL, you often do a better job at understanding posts than I do! (When I ask a question I pose it very precisely & accurately! :) )

    OK, I will think about this, at least for Linux. (You can play more easily with pipes & redirection under Linux than under Windows.) I note the OP has not declared if he has a specific target OS....



  • @jsulm
    OK, so (to help me think), in darling Perl this is:

    open(STDOUT, "| process2");
    print STDOUT "stuff to STDOUT";
    close(STDOUT);
    


  • The first, easiest, laziest Qt solution if it is acceptable is along the lines of:

    // pre-send all output from self/parent program to temporary file
    QString filename;
    QProcess process2;
    process2.setStandardInputFile(filename);
    process2.start("command2");
    // delete temporary file
    

    This is because QProcess has setStandardInputFile() but not setStandardInputProcess() like it has setStandardOutputProcess().

    Whether this is acceptable depends on whether parent can generate all its output before starting child.

    Otherwise I believe (untested by me, as usual!) you can just use QProcess::write() (actually QIODevice::write()):

    QProcess process2;
    process2.start("command2");
    process2.write(...);  # This appears on process2's stdin
    process2.write(...);
    # we need to close the write channel to process2 to signal end of input
    process2.close();  # does this do that?
    

    This would need testing to see if principles work. It doesn't actually do parent's stdout to child but rather whatever parent chooses to send via explicit process2.write(...);, but is that acceptable here?

    [ P.S. https://doc.qt.io/archives/3.3/qprocess.html#writeToStdin Looks like Qt 3.x had QProcess::writeToStdin() & QProcess::closeStdin() ! But I take it those are no longer necessary as you can just do QIODevice calls. ]



  • @JNBarchan said in how to pipe qprocess' stdout to father process as stdin:

    @jsulm
    I still don't understand the question/objective, you seem to more then I do. Does "father process" mean "self process"? The way you phrase it, do you/OP mean "pipe a process's own stdout to its own stdin"?? Can you explain "clearly", then I might understand?

    I'm so sorry for my poor description, I'm not a native English speaker so I make some mistakes in jargon. And I think that "father process" means "self process".



  • @Isolde
    It's not your fault, you do your best, especially if English not your first language!

    For processes, we talk about parent process and child process. We just don't say father!

    My last post above offers you the (only( two ways I know to achieve what you are asking for. If you can afford to you the first "send-to-file" approach that at least will work and is too much code....!



  • @JNBarchan said in how to pipe qprocess' stdout to father process as stdin:

    @Isolde
    It's not your fault, you do your best, especially if English not your first language!

    For processes, we talk about parent process and child process. We just don't say father!

    My last post above offers you the (only( two ways I know to achieve what you are asking for. If you can afford to you the first "send-to-file" approach that at least will work and is too much code....!

    I think it's a little bit different from what I want. I want to pipe a child QProcess' stdout to parent process' stdin. This question could be that how can I pass a QProcess instance for my own process to the setStandardOutputProcess method?



  • @Isolde

    I think it's a little bit different from what I want. I want to pipe a child QProcess' stdout to parent process' stdin

    Darn, I wish I had understood that was what you wanted at the outset!

    This question could be that how can I pass a QProcess instance for my own process to the setStandardOutputProcess method?

    Like @jsulm wrote in an earlier post above, Qt does not offer that (AFAIK).

    You normally accomplish this via QProcess::readAllStandardOutput() from the parent --- or you can receive signal QProcess::readyReadStandardOutput() --- but I don't know how easy/possible to connect that to parent's stdin, one usually just uses the resulting data without that. That's what I'm doing at the moment in my own code.



  • @JNBarchan said in how to pipe qprocess' stdout to father process as stdin:

    -- but I don't know how easy/possible to connect that to parent's stdin, one usually just uses the resulting data without that. That's what I'm doing at the moment in my own code.

    I know this way, but my situation looks complex, because the library(libmpv) that I used only provides very high level api that only support passing option key-value pairs, so I can only passing a filename string or "-" means stdin. And unfortunately, the data source I need is provide by another program(streamlink), it support stdout. Up to now, I'm using
    streamlink -O | my-qt-program
    to make it work. But I don't deem it a best way. So I want to start streamlink inside my program and pipe its stdout into my-qt-program's stdin. Is it possible?


  • Moderators

    @Isolde If you want to start external program and read its output you can do it very easily using http://doc.qt.io/qt-5/qprocess.html#readyReadStandardOutput and http://doc.qt.io/qt-5/qprocess.html#readAllStandardOutput
    You do not need setStandardOutputProcess for that at all.



  • @jsulm My situation is a little complex, I explained in the last reply.


  • Moderators

    @Isolde "So I want to start streamlink inside my program and pipe its stdout into my-qt-program's stdin" - why do you want to pipe it into your stdin instead of simply reading its output like I suggested?



  • @jsulm Because libmpv only support passing filename string or "-" that means read from stdin...



  • @Isolde said in how to pipe qprocess' stdout to father process as stdin:

    So I want to start streamlink inside my program and pipe its stdout into my-qt-program's stdin. Is it possible?

    That's why I wrote earlier "but I don't know how easy/possible to connect that to parent's stdin". Neither I nor seemingly @jsulm know how to change a running Qt program's stdin.

    You may safely assume that the QProcess approach is not going to work in the running parent program. One can guess that this refers to only a "sub-process", not the current process. I know what sort of code they will have written for the redirection, and they will be offering it only as they start a sub-process. What you need is a "redirect current stdin" call, and I don't see Qt offering that.

    If you are Linux only, I can tell you how to do it in C, which will presumably be reflected in C++, or you could look that up. I think it will "work" in that Qt's stdin will reflect the change, but you would not be doing the redirection or the sub-process spawning as Qt calls. Which may not be attractive.

    Alternatively you can write simple shell scripts as a "wrapper" when launching your Qt application. You could even write another small Qt application to invoke your current Qt application in the right way if you prefer!


  • Lifetime Qt Champion

    Hi,

    As already suggested, you can use QProcess and its channels communication API to process the output of mpv within your application. From the looks of it, there's no need for piping anything.



  • @SGaist But what I want is to input data into libmpv...



  • @JNBarchan Thank you for your patient help, I'll write a shell script to wrap them.



  • @Isolde
    I do think if you can manage with that it will be a lot simpler than trying to do it from Qt.

    Now that I have understood your objective, I will say that there is nothing wrong about it as a desired facility in Qt. However, so far as I can see (and I have Googled a lot) Qt does not offer any means of redirecting a parent process's (not QProcess) own stdin/stdout/stderr from/to a piped child process, and that is actually a lacking feature in its otherwise comprehensive library.



  • @JNBarchan I found a workaround.
    Now I using QProcess's startDetached() like

            QProcess* restart;
            restart = new QProcess;
            restart->startDetached("bash -c \"streamlink -O | my-qt-program \"");
            exit(0);
    

    It works well!



  • @Isolde
    Yes, you mean, you have written that as a second Qt application which does this to invoke your original Qt application, instead of a script file. Which is what we were suggesting :) [EDIT: Or, do you mean you actually do this from within your original "my-qt-program"?]


  • Moderators

    @JNBarchan said in how to pipe qprocess' stdout to father process as stdin:

    Or, do you mean you actually do this from within your original "my-qt-program

    That would be an endless loop :-)



  • @JNBarchan said in how to pipe qprocess' stdout to father process as stdin:

    is

    Not quite. I just add a simple if statement that determine whether to execute this restart code like

        if(QCoreApplication::arguments().at(1) != "bypass-parser")
        {
            QProcess* restart;
            restart = new QProcess;
            restart->startDetached("bash -c \"streamlink " + parser.value(urlOption) + " " + parser.value(streamOption) + " -O | " + QCoreApplication::applicationFilePath() + " bypass-parser " + parser.value(urlOption) + "\"");
            exit(0);
        }
    


  • @jsulm I'm sorry. They are not the whole codes, I post them completely in the last reply.


  • Moderators

    @Isolde You should not exit a Qt app like this, use http://doc.qt.io/qt-5/qcoreapplication.html#exit instead. Also there is no need to allocate QProcess on the heap. And in this particular case there is even no need for a QProcess instance at all as startDetached is static:

    if(QCoreApplication::arguments().at(1) != "bypass-parser")
    {
        QProcess::startDetached("bash -c \"streamlink " + parser.value(urlOption) + " " + parser.value(streamOption) + " -O | " +     QCoreApplication::applicationFilePath() + " bypass-parser " + parser.value(urlOption) + "\"");
        QCoreApplication::exit(0);
    }


  • @jsulm Got it. I'll amend it. Thank you very much.



  • @jsulm said in how to pipe qprocess' stdout to father process as stdin:

    @JNBarchan said in how to pipe qprocess' stdout to father process as stdin:

    Or, do you mean you actually do this from within your original "my-qt-program

    That would be an endless loop :-)

    That's why I asked, and he has posted to show how he detects....



  • @jsulm said in how to pipe qprocess' stdout to father process as stdin:

    @Isolde You should not exit a Qt app like this, use http://doc.qt.io/qt-5/qcoreapplication.html#exit instead. Also there is no need to allocate QProcess on the heap. And in this particular case there is even no need for a QProcess instance at all as startDetached is static:

    if(QCoreApplication::arguments().at(1) != "bypass-parser")
    {
        QProcess::startDetached("bash -c \"streamlink " + parser.value(urlOption) + " " + parser.value(streamOption) + " -O | " +     QCoreApplication::applicationFilePath() + " bypass-parser " + parser.value(urlOption) + "\"");
        QCoreApplication::exit(0);
    }
    

    There is a strange problem, my program won't exit with QCoreApplication::exit(0);(but it could exit normally with exit(0)), I saw two windows with QCoreApplication::exit(0);. And the terminal output indicated that the old process had run into the GUI drawing step.


  • Lifetime Qt Champion

    So you want to control mpv from your application ?


Log in to reply
 

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