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. Correctly use QProcess to read stdout and write stdin
Forum Updated to NodeBB v4.3 + New Features

Correctly use QProcess to read stdout and write stdin

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 4 Posters 2.2k Views 2 Watching
  • 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.
  • SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote on last edited by
    #2

    Hi and welcome to devnet,

    Did you try using the asynchronous API ?
    What about passing the parameters as a QStringList as is recommended ? Does it yield the same result ?

    There's no error checks done, you should add them.

    Interested in AI ? www.idiap.ch
    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

    1 Reply Last reply
    2
    • M Offline
      M Offline
      MNorvalls
      wrote on last edited by
      #3

      Hi @SGaist, thanks for the reply!

      I can't use the asynchronous as I cannot proceed to other commands and hardware controls until I can verify these commands have taken successfully. I had also tried passing the QStringList as the second argument into start() and also tried adding QIODevice::ReadWrite as the third arg as well.

      What Error checks are you referring to? Error checks in the QProcess object?

      I did try "emit updateTestProgressText("QProcess Error: " + vivadoConn.errorString());" and got "QProcess Error: Process operation timed out"

      I should add that I can run the same program with the same arguments and environment in a batch script in windows, and get the tool command line to show.

      Thank you for your time!

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #4

        @MNorvalls said in Correctly use QProcess to read stdout and write stdin:

        and get the tool command line to show.

        What do you mean by that ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • M Offline
          M Offline
          MNorvalls
          wrote on last edited by
          #5

          Running this executable from the command prompt has the tool execute a CLI based TCL command line to interface with their Xilinx tools. You can tell the tool command line is active because instead of the cmd prompt "C:/>", the tool prompt becomes "vivado_lab%", that is what I mean by getting the tool command to show.

          Does that make sense? I have also included a screenshot below :)

          7e0e8c17-f019-48ed-a566-09419d9a5cee-image.png

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #6

            One thing I just saw, split the "-mode" and "tcl" in the argument list. Each element that appears on the command line is a separate element of the list.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            1
            • M Offline
              M Offline
              MNorvalls
              wrote on last edited by
              #7

              So, I was not using the argument list in that snippet of code but had tried it before and it didn't work. With your suggestion, the arguments now work (process does not crash immediately). I was tagging them onto the command string because I could get the process to run before in that case. I assume passing the arguments in a QStringList is the proper way to use QProcess::start() so I will use that moving forward.

              I have tried both of these argument methods and they both run because if I change the mode to gui, I get the Xilinx GUI window after a short amount of time.

              Unfortunately, passing arguments the way you recommended still yields no output when reading.

              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #8

                Does it open it in a new command line window or in the same one that you call the application in ?

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                0
                • M MNorvalls

                  Hello,

                  I am trying to automate programming of an FPGA in a Qt application. I need to use Xilinx Vivado to control a Xilinx programming pod to program the FPGA.

                  There aren't any API plugins they offer that I know of, but the Vivado tool has a command line option. I am trying to start the vivado_lab.exe with 3 arguments and a specific environment needed to run, as a QProcess. I have setup the environment with QProcessEnvironment object, but I get no output when running the code. I know the tool starts, as I can find its PID from windows when I run my code. But when I try to read the stdout of the process I see no output. I am expecting the command line prompt "vivado_lab%".

                  The code I am referring to is below, and runs inside of a thread.

                              QProcess vivadoConn;
                              vivadoConn.setProcessChannelMode(QProcess::MergedChannels);
                  
                              // Command to start vivado in tcl mode
                              //QString vivadoCmd = l_toolDirs.xilinxToolDir.toUtf8() + " -nojournal -nolog -mode tcl";
                  
                              // Start the Vivado command line
                              if(l_testInProgress)
                              {
                                  emit updateTestProgressText("Starting Vivado, Please wait...\n");
                  
                                  QStringList args;
                                  args.append("-mode tcl");
                                  args.append("-nojournal");
                                  args.append("-nolog");
                  
                                  QProcessEnvironment vivadoEnv;
                                  vivadoEnv.insert("HDI_APPROOT","C:/Xilinx/Vivado_Lab/2018.2");
                                  vivadoEnv.insert("RDI_APPROOT","C:/Xilinx/Vivado_Lab/2018.2");
                                  vivadoEnv.insert("RT_LIBPATH","C:/Xilinx/Vivado_Lab/2018.2/scripts/rt/data");
                                  vivadoEnv.insert("RT_TCL_PATH","C:/Xilinx/Vivado_Lab/2018.2/scripts/rt/base_tcl/tcl");
                                  vivadoEnv.insert("TCL_LIBRARY","C:/Xilinx/Vivado_Lab/2018.2/tps/tcl/tcl8.5");
                                  vivadoEnv.insert("XILINX_PLANAHEAD","C:/Xilinx/Vivado_Lab/2018.2");
                                  vivadoEnv.insert("XILINX_VIVADO","C:/Xilinx/Vivado_Lab/2018.2");
                                  vivadoEnv.insert("Path","C:/Xilinx/Vivado_Lab/2018.2/bin;C:/Xilinx/Vivado_Lab/2018.2/lib/win64.o;C:/Xilinx/Vivado_Lab/2018.2/tps/win64/jre/bin/server;C:/Xilinx/Vivado_Lab/2018.2/tps/win64/jre/bin;");
                  
                                  QString xilinxvivadoResp, test1;
                                  //vivadoConn.setProgram(l_toolDirs.xilinxToolDir.toUtf8());
                                  vivadoConn.setProcessEnvironment(vivadoEnv);
                                  //vivadoConn.setArguments(args);
                                  vivadoConn.start(l_toolDirs.xilinxToolDir.toUtf8() + " -nojournal -nolog -mode tcl");
                  
                                  vivadoConn.waitForStarted();
                  
                                  qint64 vivado_pid = 0;
                                  vivado_pid = FindProcessId(L"vivado_lab.exe");
                  
                                  xilinxvivadoResp = vivadoConn.readAllStandardOutput();
                                  test1 = vivadoConn.readAllStandardError();
                                  while(vivadoConn.waitForReadyRead(1000)) xilinxvivadoResp += vivadoConn.readAllStandardOutput();
                  
                                  emit updateTestProgressText("Output String: " + xilinxvivadoResp + "\n");
                                  emit updateTestProgressText("Error String: " + test1 + "\n");
                  
                                  emit updateTestProgressText("Process ID for Vivado is: " + QString::number(vivado_pid) + "\n");
                  
                                  if((!xilinxvivadoResp.contains("vivado_lab%")) || (vivadoConn.state() == QProcess::ProcessState::NotRunning))
                                  {
                                      emit updateTestProgressText("Error connecting to Xilinx Vivado!\n\nExiting!\n");
                                      vivadoConn.write("exit");
                                      vivadoConn.kill();
                                      threadStopping();
                                      return;
                                  }
                  
                                  // Increment progress
                                  for(auto i = 10; i <= 20; i++)
                                  {
                                      emit updateTestProgress(i);
                                  }
                              }
                  
                              // Open a connection to the Xilinx pod hardware from vivado
                              if(l_testInProgress)
                              {
                                  vivadoConn.write("open_hw");
                                  this->sleep(3); // Wait for app response
                  
                                  QString xilinxvivadoResp = vivadoConn.readAll();
                  
                                  if((!xilinxvivadoResp.contains("vivado_lab%")) || (vivadoConn.state() == QProcess::ProcessState::NotRunning))
                                  {
                                      emit updateTestProgressText("Error opening Xilinx hardware!\n\nExiting!\n");
                                      vivadoConn.write("exit");
                                      vivadoConn.kill();
                                      threadStopping();
                                      return;
                                  }
                  
                                  // Increment progress
                                  for(auto i = 20; i <= 30; i++)
                                  {
                                      emit updateTestProgress(i);
                                  }
                              }
                  
                              // Connect to the new Xilinx hardware connection
                              if(l_testInProgress)
                              {
                                  vivadoConn.write("connect_hw_server");
                                  QThread::sleep(10); // Wait for app response
                  
                                  QString xilinxvivadoResp = vivadoConn.readAll();
                  
                                  if((!xilinxvivadoResp.contains("connect_hw_server: Time")) || (vivadoConn.state() == QProcess::ProcessState::NotRunning))
                                  {
                                      emit updateTestProgressText("Error connecting to Xilinx hardware!\n\nExiting!\n");
                                      vivadoConn.write("exit");
                                      vivadoConn.kill();
                                      threadStopping();
                                      return;
                                  }
                  
                                  // Increment progress
                                  for(auto i = 30; i <= 40; i++)
                                  {
                                      emit updateTestProgress(i);
                                  }
                              }
                  
                              // Check for Xilinx devices
                              if(l_testInProgress)
                              {
                                  vivadoConn.write("get_hw_devices");
                                  QThread::sleep(5); // Wait for app response
                  
                                  QString xilinxvivadoResp = vivadoConn.readAll();
                  
                                  if((!xilinxvivadoResp.contains("No matching hw_devices were found")) || (vivadoConn.state() == QProcess::ProcessState::NotRunning))
                                  {
                                      emit updateTestProgressText("Error: Could not find Xilinx FPGA!\n\nExiting!\n");
                                      vivadoConn.write("exit");
                                      vivadoConn.kill();
                                      threadStopping();
                                      return;
                                  }
                  
                                  // Increment progress
                                  for(auto i = 40; i <= 50; i++)
                                  {
                                      emit updateTestProgress(i);
                                  }
                              }
                              threadStopping();
                  
                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #9

                  @MNorvalls said in Correctly use QProcess to read stdout and write stdin:

                  I am expecting the command line prompt "vivado_lab%".

                  It may be that the shell will not send an output prompt if it detects that standard input is not a terminal.

                  Outside of Qt, you should be able to test redirecting stdin or stdout from/to a pipe (<, >, |) to see what can actually be captured.

                  And you should be capturing stderr as well as stin/out, if you are not doing so already.

                  1 Reply Last reply
                  0
                  • Christian EhrlicherC Online
                    Christian EhrlicherC Online
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote on last edited by
                    #10

                    @MNorvalls said in Correctly use QProcess to read stdout and write stdin:

                    args.append("-mode tcl");

                    This is wrong, they're two arguments.

                    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                    Visit the Qt Academy at https://academy.qt.io/catalog

                    JonBJ 1 Reply Last reply
                    0
                    • Christian EhrlicherC Christian Ehrlicher

                      @MNorvalls said in Correctly use QProcess to read stdout and write stdin:

                      args.append("-mode tcl");

                      This is wrong, they're two arguments.

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #11

                      @Christian-Ehrlicher We've moved on from that now, Christian :)

                      1 Reply Last reply
                      0
                      • M Offline
                        M Offline
                        MNorvalls
                        wrote on last edited by
                        #12

                        Thanks guys, yes it seems to be the executable that does not want to output its stdout in the tcl mode. I can see output if I call it in GUI mode (but obviously the GUI starts up instead). I am just going to have it write output to a file unfortunately.

                        @SGaist The tcl command line opens in the same command window. When calling the GUI mode, some output shows in the command window, and then the GUI appears in its own window.

                        @JonB I will give the command line piping a try as well for curiosity's sake, thank you.

                        Thanks for the help!

                        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