PDA

View Full Version : [SOLVED] QProcess Java Application Not Working



2lights
3rd December 2013, 10:33
Good Day,

I'm having a problem calling a java function from Qt

This is what I have in Qt



QString program;
program = "./java";

QStringList arg;
arg << "-jar";
arg << "D:/Visual.jar";
arg << "UniqueFilter "; //name of function within Visual.jar
arg << "D:/inputImage.bmp"; //input image
arg << "D:/result.txt"; //output file
arg << "D:/resultImage.png"; //output image

QProcess *myProcess = new QProcess(this);
myProcess->start(program, arg);



This is the actual function call from Command prompt (cmd) works



//in cmd
java -jar D:/Visual.jar UniqueFilter D:/inputImage.bmp D:/result.txt D:/resultImage.png



So Basically I'm using Java as my program name
and all other inputs as arguments.
It does not work

What is the easiest way of calling java from Qt
This java call is just needed for its resulting Image and Qt will process the rest

Your help is much appreciated
Kind Regards

stampede
3rd December 2013, 10:44
program = "./java";
So it looks like your command is equivalent to

./java -jar D:/Visual.jar UniqueFilter D:/inputImage.bmp D:/result.txt D:/resultImage.png
Maybe this way :

program = "java";

2lights
3rd December 2013, 10:51
No, it does not work
Any other ideas ?

stampede
3rd December 2013, 11:06
Connect to "error", "started" and "finished" signals of QProcess and call waitForStarted() on it. If you want to wait for this command to complete before doing anything else in your app, call waitForFinished().
How do you check for errors now ?

anda_skoa
3rd December 2013, 11:37
Did you start your program from the same cmd shell that you can run java on?
If not, have you checked that your program sees the right environment? E.g. correct value of PATH?

Cheers,
_

2lights
3rd December 2013, 11:48
QProcess *myProcess = new QProcess(this);
myProcess->start(program, arg);

qDebug() << myProcess->state(); //Ref 1
qDebug() << myProcess->error(); //Ref 2


Within the enum QProcess::ProcessState (Ref 1) i get value 0, which by Qt doc it represents
"The process is not running."
and in the value for error (Ref 2) I get value 0, which by Qt doc it represents
"The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program."
At the moment I just check manually in specified dir to see if Output image has been created!

Should I maybe invoke Command prompt(cmd) from Qt & then send the arguments to cmd

I can call the java function from the cmd ("Windows Command Processor")
I assumed that adding the same arguments to the QProcess will provide the same results.

correct value of PATH?, What exactly should i check for or add?

Added after 5 minutes:

Tested the Java call from "Windows Command Processor" -> cmd it works

I assumed calling it from Qt would be the same process
What exactly do i look for within the PATH or What should I add?

Should the Java and all the parameters be in the same diretory as the Qt project

Or maybe should I call "cmd" from Qt with the predetermined arguments, not sure if it can be done though

stampede
3rd December 2013, 11:52
QProcess will start your command asynchronously, you'll have to wait before checking if its running or any error occured. From Qt docs:

Processes are started asynchronously, which means the started() and error() signals may be delayed. Call waitForStarted() to make sure the process has started (or has failed to start) and those signals have been emitted.

2lights
3rd December 2013, 12:58
Tried multiple methods but to no avail :(

Are there any #includes I should add to my .cpp file to call function
My function just initializes the the QProcess as above and tries to run it

Do I need to create a Java virtual machine before I try calling QProcess

Is there any simple tutorial I can follow?

Kind Regards

stampede
3rd December 2013, 13:09
My function just initializes the the QProcess as above and tries to run it
And it does not wait for it to start and does not check for error values.


{
// ...
QProcess *myProcess = new QProcess(this);
connect(myProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(checkError(QProcess::ProcessError)));
connect(myProcess, SIGNAL(started()), this, SLOT(processStarted()));
connect(myProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processExited(int,QProcess::ExitStatus)));
myProcess->start(program, arg);
// .. here you exit the current function and wait for process to start / fail to start
}

void MyClass::processStarted(){
qDebug() << "Hurray ! MyProcess started!";
}

void MyClass::checkError(QProcess::ProcessError err){
qDebug() << "Process error: " << err;
}

void MyClass::processExited(int exitCode, QProcessExitStatus status){
qDebug() << "Process exited with code: " <<exitCode << ", status: " << status;
}



Alternative is to call waitForFinished() after start(), but this can freeze the gui.
It is important to understand the asynchronous nature of QProcess, this:

QProcess *myProcess = new QProcess(this);
myProcess->start(program, arg);

qDebug() << myProcess->state(); //Ref 1
qDebug() << myProcess->error(); //Ref 2
will not work correctly in most of the cases, because you check the status and error value of QProcess before it is initialized and started.

anda_skoa
3rd December 2013, 14:18
Tested the Java call from "Windows Command Processor" -> cmd it works

I assumed calling it from Qt would be the same process

Sure, but the cmd shell might see a different environment than your program. Have you tried running your program from cmd?



What exactly do i look for within the PATH or What should I add?

The path to the "java" executable, otherwise it has no way of finding it, right?

Alternatively call java with it's full path. Not sure though how java finds it's own classpath.

Cheers,
_

2lights
3rd December 2013, 15:35
Created a .bat file with all arguments then I called cmd
Its not an efficient method but it seems to work



QProcess p;
p.start("cmd.exe", QStringList() << "/c" << "c:\\mybat.bat");
if (p.waitForStarted())
{
p.waitForFinished();
qDebug() << p.readAllStandardOutput();
}
else
qDebug() << "Failed to start";


Taken from http://www.qtforum.org/article/21366/how-to-open-execute-any-batch-file-using-qt.html

Your comments on a better solution

Kind Regards

stampede
3rd December 2013, 15:54
Thanks guys tried what you guys posted
Ok, so what is the output of the qDebug() in slots connected to error, exitCode etc. signals ?

I just tested calling a class from java .jar file with QProcess, worked without problems. Here is the java class:



public class Test {
public static void main(String[] args) {
if (args.length > 0)
System.out.println(args[0]);
else
System.out.println("no args given");
}

}

So it will print first argument or "no args given" in case of 0 args.
I created a .jar file (with eclipse "export" option) and placed it in D:/test_java/test.jar.
Next, the Qt project:


// runJava.h
#ifndef _RUN_J_H_
#define _RUN_J_H_

#include <QObject>
#include <QProcess>
#include <QDebug>

class RunJava : public QObject{
Q_OBJECT
public:
RunJava(QObject * parent = NULL) : QObject(parent){
}
~RunJava(){
}
void runJava(){
QProcess *myProcess = new QProcess(this);
connect(myProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(checkError(QProcess::ProcessError)));
connect(myProcess, SIGNAL(started()), this, SLOT(processStarted()));
connect(myProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processExited(int,QProcess::ExitStatus)));
connect(myProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(processReadyRead()));
const QString program = "java";
QStringList arg;
arg << "-jar";
arg << "D:/test_java/test.jar";
arg << "whatever";
myProcess->start(program, arg);
}
private slots:
void processStarted(){
qDebug() << "Hurray ! MyProcess started!";
}

void checkError(QProcess::ProcessError err){
qDebug() << "Process error: " << err;
}

void processExited(int exitCode, QProcess::ExitStatus status){
qDebug() << "Process exited with code: " <<exitCode << ", status: " << status;
emit done();
}
void processReadyRead(){
if (QProcess * proc = qobject_cast<QProcess*>(sender())){
qDebug() << "process output: " << proc->readAllStandardOutput();
}
}
signals:
void done();
};

#endif


main.cpp:


#include <QCoreApplication>
#include "runJava.h"

int main(int argc, char ** argv){
QCoreApplication app(argc,argv);
RunJava jv;
QObject::connect(&jv, SIGNAL(done()), &app, SLOT(quit()));
jv.runJava();
return app.exec();
}

.pro:


################################################## ####################
# Automatically generated by qmake (2.01a) Wt 3. gru 15:45:58 2013
################################################## ####################

TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .

CONFIG += console

# Input
HEADERS += runJava.h
SOURCES += main.cpp



After running the app, it outputs:


Hurray ! MyProcess started!
process output: "whatever
"
Process exited with code: 0 , status: 0