Parent and child stdout/stdin communication using QProcess
-
Hi everyone,
I have searched online for many days as well as trying different methods for my code but none of the methods seem to be working for me. I have three applications (one is a C++ console and two are Qt GUI application). By using QProcess, I set one of my Qt GUI application (MoveGUI.exe) as the parent process of the other GUI application (TargetGame.exe) and my C++ console (MoveMovement.exe). I am using Windows 7, 64-bit platform. My Qt creator version is 3.0.1 (based on Qt.5.2.1). I am new to Qt creator as well as coding for communication between different applications - apologies if I am asking really trivial questions.
I have successfully implemented the parent process (MoveGUI.exe) to receive output data from TargetGame.exe and MoveMovement.exe by coding in the MoveGUI.exe with:
@MoveMovementProcess = new QProcess();
TargetGameProcess = new QProcess();
MoveMovementProcess->start("MoveMovement.exe");
TargetGameProcess->start("TargetGame.exe");
connect(TargetGameProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(UpdateTestingProgress()));
connect(MoveMovementProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(PassToTargetGame())); @Where UpdateTestingProgress() will update the progress bar on the MoveGUI UI, and PassToTargetGame() is to pass the received data from the MoveMovement.exe in MoveGUI to the other child process TargetGame.exe (code is below).
I coded the programs so that the MoveMovement.exe starts to output to stdout when the cursor is at top center part of the screen, and the TargetGame.exe starts reading from stdin when the cursor is at top center part of the screen as well.
The problem I am encountering was that I tried using std::cout, the write() function, the putchar() function in MoveGUI.exe (parent process) to output to the child process TargetGame.exe, and none of it seems to be working... Below is the output to stdout part in the MoveGUI.exe:
@void MainWindow::PassToTargetGame()
{
QByteArray MoveMovementinput;
int MoveMovementoutput;// this is reading correctly from the MoveMovement.exe MoveMovementinput=MoveMovementProcess->readAllStandardOutput(); MoveMovementoutput = (int) MoveMovementinput [0]; //this is working. It is outputting to the MoveGUI terminal correctly. std::cout<< (char)MoveMovementoutput; std::cout.flush();
} @
In my childprocess TargetGame.exe, I have the following code to read in from stdin. I have tried many methods, and all seems to be causing the program to freeze or reading 0 instead of 1 or 2 that was sent from the MoveMovement.exe and verified with the MoveGUI.exe. The below two methods are the ones that did not cause my program to freeze but always read 0.
@//method 1:
QFile stdinfile;
stdinfile.open(stdin,QIODevice::ReadOnly);
stdinfile.read(buffer);
qDebug()<<"what's in the buffer"<<buffer; //gives me 0 @@//method 2:
int test;
if(std::cin != NULL){
std::cin>>test;
qDebug()<<"test value" <<test; // this also gives me a 0
}@I have also seen many comments suggesting QLocalSocket, QSharedMemory, etc., I tried to implement those but I failed to make it work because I don't quite understand how to use those...
Is there anything wrong with my code? How can I fix it? Any suggestions would be greatly appreciated.
Thank you very much in advance!
Tina -
This is what is called IPC (Inter-Process Communication), and is usually done using some ready-made solutions (local sockets, networks sockets, QtDbus, QSharedMemory), although your solution could also work, in theory.
Here are the issues I see in your code:
- move connect statements before the calls to start the QProcess. Right now you could be missing part of the communication
- use QProcess::write() and QProcess::readAll() to push and pull the text data to and from a process; don't rely on std::cin and std::cout
- make sure you open the process in ReadWrite mode: "link":http://qt-project.org/doc/qt-5/qprocess.html#start-3
- you can also use direct standard output rerouting: "link":http://qt-project.org/doc/qt-5/qprocess.html#setStandardOutputProcess
-
Hi sierdzio,
Thank you very much for your reply :) I looked into all the comments you have - the connect statements are now before the calls to start the QProcess and I opened the process in ReadWrite mode as well. Sadly, this does not seem to make a difference to my current situation of not being able to read parent process's output from my child process...
As for your second and fourth comment, I am not entirely sure how to achieve that.
For comment #2: wouldn't QProcess::write() and QProcess::readAll() both be happening in the parent process? I would like the child process (in this case, the TargetGame.exe) to read outputs from the parent process (MoveGUI.exe) so that it is able to execute some commands within the application.
For comment #4: I got stuck after putting the following code into the parent process:
@MoveMovementProcess->setStandardOutputProcess(TargetGameProcess);@Does this line of code mean that anything from the stdout of the MoveMovement.exe will get directly rerouted to stdin of TargetGame.exe? I tried to read stdin from the TargetGameProcess.exe but still with no luck... Now my program always freeze whenever I try to read std::cin using .get() or .read() or .readsome(), etc.
Is it possible for you to explain more about how to approach this problem using your comment #2 and #4? Or provide a more specific example on how I can approach this?
Note that in my header file, the process were defined as:
@QProcess *MoveMovementProcess;
QProcess *TargetGameProcess;@Thank you very much!
Tina[quote author="sierdzio" date="1413180542"]This is what is called IPC (Inter-Process Communication), and is usually done using some ready-made solutions (local sockets, networks sockets, QtDbus, QSharedMemory), although your solution could also work, in theory.
Here are the issues I see in your code:
- move connect statements before the calls to start the QProcess. Right now you could be missing part of the communication
- use QProcess::write() and QProcess::readAll() to push and pull the text data to and from a process; don't rely on std::cin and std::cout
- make sure you open the process in ReadWrite mode: "link":http://qt-project.org/doc/qt-5/qprocess.html#start-3
- you can also use direct standard output rerouting: "link":http://qt-project.org/doc/qt-5/qprocess.html#setStandardOutputProcess
[/quote]
-
#2 - indeed, readAll() has no place in your parent class. I have not thought your use case well before posting my reply.
I think all this would be easier if you were using network communication hooked to localhost. Regarding your application freezing: reading from stdin will not play well with the event loop of your application, as this operation is blocking.