Communicating to a C++ program from java - java

I want to execute a external .exe program from within java. The .exe is a CLI application which takes input in runtime( scanf() ) and outputs depending on the input. I can call the program to execute from java using
Process p = Runtime.getRuntime().exec("cmd /c start a.exe");
instead of
Process p = Runtime.getRuntime().exec("cmd /c start a.exe");
But I think it is also possible to call a program from within java. I have my whole program written in C++ just need a GUI which is written in java. There are a few things to notice:=
1) The communication with the .exe should be runtime (not through main(args) )
2) The java program should take the outputs and store in some variable / panel to use for future
3) Program to be executed can differ ( for example user may select a .exe that doesnt take any input at all)
........So basically the java GUI will act as a RuntimeEnv
public void runEXE()
{
String s = null;
try {
Process p = Runtime.getRuntime().exec("cmd /c a.exe");
System.exit(0);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}
}
I know there are a lot of questions about this topic out there. But i cant find any of them much useful.

Rather ugly little function that I use. This takes in the command to be passed to Runtime.getRuntime().exec, then saves the results into a String, and returns the String at the end. You can pick whether you only want the last line (or all output) and whether you want to save the stdout or stderr string from the process.
private static String systemResult(String cmd, boolean append, boolean useErr)
{
String result = "";
try{
// spawn the external process
//printCmd(cmd);
Process proc = Runtime.getRuntime().exec(cmd);
LineNumberReader lnr1 = new LineNumberReader(new InputStreamReader(proc.getErrorStream()));
LineNumberReader lnr2 = new LineNumberReader(new InputStreamReader(proc.getInputStream()));
String line;
int done = 0;
while(lnr1 != null || lnr2 != null){
try{
if(lnr1.ready()){
if((line = lnr1.readLine()) != null){
//System.err.println("A:" +line);
if(useErr){
if(append) result = result + line + "\n";
else result = line;
}
}
}else if(done == 1){
done = 2;
}
}catch(Exception e1){
try{ lnr1.close(); }catch(Exception e2){}
lnr1 = null;
}
try{
if(lnr2.ready()){
if((line = lnr2.readLine()) != null){
//System.err.println("====>Result: " + line);
if(!useErr){
if(append) result = result + line + "\n";
else result = line;
}
}
}else if(done == 2){
break;
}
}catch(Exception e1){
try{ lnr2.close(); }catch(Exception e2){}
lnr2 = null;
}
try{
proc.exitValue();
done = 1;
}catch(IllegalThreadStateException itsa){}
}
if(lnr1 != null) lnr1.close();
if(lnr2 != null) lnr2.close();
try{
proc.waitFor();
}catch(Exception ioe){
}finally{
try{
proc.getErrorStream().close();
proc.getInputStream().close();
proc.getOutputStream().close();
}catch(Exception e){}
proc = null;
}
}catch(Exception ioe){
}
return result;
}

You could use JNI as #linuxuser27 suggests, or you could use SWIG which helps to make the process of communicating from Java --> C++ a little less painful.

Google Protocol Buffers would be a good option for Java/C++ interoperability.
Protocol buffers are Google's
language-neutral, platform-neutral,
extensible mechanism for serializing
structured data – think XML, but
smaller, faster, and simpler. You
define how you want your data to be
structured once, then you can use
special generated source code to
easily write and read your structured
data to and from a variety of data
streams and using a variety of
languages – Java, C++, or Python.

I would look at JNI and use some type of IPC to communicate with the C++ project.
Update:
JNI is a way for Java to interface with the underlying native environment the JRE is running on. This method would require you to create a DLL that is loaded into the JRE when your Java program starts. This JNI DLL would then contain a method which could be called from within your Java program that would pass data into the JNI DLL that could then communicate to the C++ project via a named pipe or shared memory.
The named piped would be create using the CreateNamedPipe Win32 API. Within the JNI DLL you would most likely create a server and in the C++ project you would create the client. Note that the server example is multi-threaded but can easily be converted to a single thread model for simplicity.
Note that this is not a simple task. The other answers offer some approaches that are easier, JNA and passing data to the C++ project via stdin.

A couple of things:
First and foremost, if you haven't done so, read this critically important article: When Runtime.exec won't
Next, there are several ways for Java to communicate to other applications, and probably the easiest is via standard input and output streams. Have you tried using these?
Next there's JNI and the easier JNA, but you stated that your C++ program is running via CLI which suggests to me that you have a .NET dll, not a true Windows dll. Is this so? If so, it would make communication between Java and C++ more difficult.

You can execute .exe programs directly. You just need to supply the full path. Relative path will also be ok.
You can use pipes to interface with an external process: Sending Input to a Command, Reading Output from a Command

The solution can be found here
Problem getting output and passing input to a executing process running under java

Related

How to create a 2 way communication between Java and Python

I am pretty new to both Java and Python, although I have some experience in programming. For an assignement, I need to create a program which uses Java in some way. My project would use Java as an UX, and Python for signal processing and feature extraction, since it has some good tools for that.
However, my question is how to establish communication between both programse. Maybe this question has been asked before, but since I do not know the best terms, I could not find answers.
In my Java Program, I can get the file path to a .csv file, send it to Python, and Python returns the original signals and processed signals. For that, I wrote:
private static void sendPython(String path, JTextField console)
{
String pathPython = "C:\\Users\\gonca\\Desktop\\untitled0.py";
String [] cmd = new String[3];
cmd[0] = "python";
cmd[1] = pathPython;
cmd[2] = path;
Runtime r = Runtime.getRuntime();
try
{
Process p = r.exec(cmd);
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String s = "";
while((s = in.readLine()) != null)
{
console.setText(s);
}
}
catch (IOException e)
{
console.setText("Unable to run python script");
}
}
I was thinking of having the py script output the signals in separated lines, with values separated by "," or ";", and using the BufferedRead to read each line, separate the values and create a new ArrayList from the separated values.
However, before starting working harder to do that, I would like to know if that is the best way to proceed, or is there a more efficient way to do it.
There are more ways to do that:
Solution 1:
Use the python library from java with System.loadLibrary, and call the python method. (here is an example using C/C++: Calling a python method from C/C++, and extracting its return value)
Solution 2:
Launch python as another process, and use D-Bus (or something similar) to communicate with it.
Since you have not mentioned how robust your application is I can think of a solution which can be used if you are planning for a higher level architecture.
Create a python based web application (HTTP server) with all logic to process your files.
Create a java app which can communicate via HTTP python server to get the CSV processed information.
Try to avoid Runtime execution of commands with in your codes that faces user as if it not is properly managed there is always a chance for security breach

Compiling and communication with shell application in Android/Java

I have a command line application (also it's source code in C language). I want to use it in my first android application.
Here are my questions:
I have a compiled executable for mac. Should I recompile it for android? If yes, how?
Is it possible to have a two way communication with an executable in shell in Java/Android?
I'm looking for something like:
Runtime.getRuntime().exec(cmd);
After a lot of googling, that line of code was only thing that I found. But I don't want to close the executable after each call (it communicates with a server on the internet). Here is what I want to do:
1. Open shell executable
2. write AAA
3. read line
4. write BBB
5. read line
6. write CCC
...
98. write XYZ
99. read line
100. close executable
Note that there may be nothing to read, and it shouldn't wait for it.
Yes, you need recompile it with NDK. How: you can find more information on official Android site, where examples also present.
Yes its also possible to do that, and there are two ways exist:
a) JNI. You need to write a wrapper for for you function, and compile a shared library
b) You can compile executable file, run it and communicate via input/output stream. Something like:
try {
Process pb = Runtime.getRuntime().exec(cmd);
String line;
BufferedReader input = new BufferedReader(new InputStreamReader(pb.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println("Input from your C/C++ app: " + line);
}
input.close();
} catch (IOException e) {
e.printStackTrace();
}

Imagemagick can't open file when executed from Java Servlet

I'm trying to convert files from png's to pdf using imagemagick and Java. I've got everything working to a place when I'm executing imagemagick command to actually merge multiple png's into one pdf. The command itself looks properly, and it works fine when executed in the terminal but my application gives me error showing that imgck can't open the file (even though it exists and I've set permissions to the folder to 777 :
line: convert: unable to open image `"/Users/mk/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/sch-java/print-1357784001005.png"': No such file or directory # error/blob.c/OpenBlob/2642.
This is my command :
/opt/local/bin/convert "/Users/mk/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/sch-java/print-1357784001005.png" "/Users/mk/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/sch-java/print-1357784001219.png" "/Users/mk/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/sch-java/complete-exportedPanel2013-01-1003:13:17.212.pdf"
And my Java code :
String filesString = "";
for (String s : pdfs){
filesString += "\""+ s + "\" ";
}
Process imgkProcess = null;
BufferedReader br = null;
File f1 = new File(pdfs[0]);
//returns true
System.out.println("OE: "+f1.exists());
String cmd = imgkPath+"convert "+ filesString+ " \""+outputPath+outName+"\"";
try {
imgkProcess = Runtime.getRuntime().exec(cmd);
InputStream stderr = imgkProcess.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
br = new BufferedReader(isr);
} catch (IOException e1) {
msg = e1.getMessage();
}
imgkProcess.waitFor();
while( (line=br.readLine() ) != null){
System.out.println("line: "+line);
}
The whole code is executed from a java servlet controller after getting request from a form. Any ideas what can cause this ? I'm using latest imgck, jdk, and osx 10.7 .
A few things:
When spawning anything but really trivial processes, it's usually better to use ProcessBuilder than Runtime.exec() - it gives you much better control
Even with ProcessBuilder, it often works better to write a shell script that does what you need. Then spawn a process to run the script. You get a lot more control in shell script than you do in ProcessBuilder
Remember that a spawned process is not a shell. It can't, for instance, evaluate expressions, or expand shell variables. If you need that, then you must execute a shell (like sh or bash). Better yet, write a shell script as described above
If all you need to do is to execute some ImageMagick commands, it would probably be easier to jmagick, a Java interface to ImageMagick - see http://www.jmagick.org/
Actually, since the you're assembling images into a PDF, the iText library - http://itextpdf.com is probably the best tool for the job, as it is native Java code, does not require spawning a native process, and will therefore be much more portable.
Solved it by adding all arguments to an arrayList and then casting it to String array.
ArrayList<String> cmd = new ArrayList<String>();
cmd.add(imgkPath+"convert");
for (int i=0, l=pdfs.length; i<l; i++){
cmd.add(pdfs[i]);
}
cmd.add(outputPath+outName);
imgkProcess = Runtime.getRuntime().exec(cmd.toArray(new String[cmd.size()]));

How do I execute an executable file from within a java file on linux?

I am trying to execute an executable file and a perl script from within a java program. I have found many topics similar to this but most of them refer to windows. I know java is platform independent and it should work anyways but it doesn't. The solution I have tried already is the one based on the java Runtime and it's exec method. It works just fine on windows but since I'm porting my program on linux I need to adapt it. As I said I need to execute an executable file that I have compiled and was written in c++ which it looks like it's working but it finishes executing with an exit value of 1. I have no idea what it means but on windows it exits with 0 and that's how it should be on linux as well (?!?!). The pearl script on the other hand does not start at all. I use the command "perl script.pl" and it exits with a value of 255. Needless to say, it doesn't do what it's supposed to.
Does anybody know another way to execute these files? Or maybe where I am wrong with my implementation?
here's the code if you want to take a look at it:
This is the one for the perl script
public static void main(String[] args){
System.out.println("Starting");
try{
String[] cmd = {"perl", "cloc-1.53.pl"};
Process pr = Runtime.getRuntime().exec(cmd);
BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line=null;
while((line=input.readLine()) != null) {
System.out.println(line);
}
int exitVal = pr.waitFor();
System.out.println("Exit code: " + exitVal);
} catch (Throwable t){
t.printStackTrace();
}
}
For the compiled file I change this:
String[] cmd = {"perl", "cloc-1.53.pl"};
with:
String cmd = "./UCC";
There should be no differece in starting processes on windows and linux.
Good article http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
Its for the old way but gives good insight.
Article converting to the new way:
From Runtime.exec() to ProcessBuilder

Interaction between Java App and Python App

I have a python application which I cant edit its a black box from my point of view. The python application knows how to process text and return processed text.
I have another application written in Java which knows how to collect non processed texts.
Current state, the python app works in batch mode every x minutes.
I want to make the python
processing part of the process: Java app collects text and request the python app to process and return processed text as part of a flow.
What do you think is the simplest solution for this?
Thanks,
Rod
I don't know nothing about Jython and the like. I guess it's the best solution if you can execute two programs without executing a new process each time the Java app needs to transform text. Anyway a simple proof of concept is to execute a separate process from the Java App to make it work. Next you can enhance the execution with all that tools.
Executing a separate process from Java
String[] envprops = new String[] {"PROP1=VAL1", "PROP2=VAL2" };
Process pythonProc = Runtime.getRuntime().exec(
"the command to execute the python app",
envprops,
new File("/workingdirectory"));
// get an outputstream to write into the standard input of python
OutputStream toPython = pythonProc.getOutputStream();
// get an inputstream to read from the standard output of python
InputStream fromPython = pythonProc.getInputStream();
// send something
toPython.write(.....);
// receive something
fromPython.read(....);
Important: chars are NOT bytes
A lot of people understimate this.
Be careful with char to byte conversions (remember Writers/Readers are for chars, Input/OutputStreams are for bytes, encoding is necesary for convertir one to another, you can use OuputStreamWriter to convert string to bytes and send, InputStreamReader to convert bytes to chars and read them).
Look into Jython - you can run Python programs directly from Java code, and interact seamlessly back and forth.
Use ProcessBuilder to execute your Python code as a filter:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class PBTest {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder("python", "-c", "print 42");
pb.redirectErrorStream(true);
try {
Process p = pb.start();
String s;
BufferedReader stdout = new BufferedReader (
new InputStreamReader(p.getInputStream()));
while ((s = stdout.readLine()) != null) {
System.out.println(s);
}
System.out.println("Exit value: " + p.waitFor());
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Expose one of the two as a service of some kind, web service maybe. Another option is to port the python code to Jython
One possible solution is jpype. This allows you to launch a JVM from Python and pass data back and forth between them.
Another solution may be to write the Python program as a filter (reading data from stdin and writing result to stdout) then run it as a pipe. However I do not know how well Java supports this - according to the Sun docs their concept of pipes only supports communication between threads on the same JVM.
An option is making the python application work as a server, listens for request via sockets (TCP).

Categories

Resources