How to call java from C++ - java

I need to run this line from my c++ program:
java -jar test.jar text1 text2
the java app will give a float value and give it to the c++ program.
How can I do this? I never call a java stuff before from my ms visual studio C++ file.

If you want strong coupling use JNI wrapper.

When I run the java command directly on my command prompt, it works. but when I run the command from the c++ file, the error says "The system cannot execute the specified program" .
here's my code, im using ms visual studio 2005 :
#include "stdafx.h"
#include <conio.h>
int _tmain(int argc, _TCHAR* argv[])
{
float value;
FILE *child = _popen("java -jar c:\simmetrics_jar_v1_6_2_d07_02_07.jar text1 ssdyr445", "r");
if (fscanf(child, "%f", &value) == 1)
{
fprintf(stdout,"Got Value from simmetrics: %f\n", value);
}
else
{
fprintf(stdout,"ERROR\n");
}
fclose(child);
return 0;
}

A simple solution is to use popen() and pclose().
The function popen(), forks() and execs() a sub processes. But it attaches the sub-processes standard-in and standard-out the stream object created by popen. Thus writting anything to the stream in the parent sends it to the standard-in of the sub-processes while anything the sub-processes writes to standard-out can be read from the stream by the parent:
double value;
FILE* child = popen("java -jar test.jar text1 text2", "r");
if (fscanf(child, "%f", &value) == 1)
{
fprintf(stdout,"Got Value: %f\n", value);
}
else
{
fprintf(stdout,"ERROR\n");
}
fclose(child);

The easiest if You can modify your java code:
write the result to environment variable (pseudo code below):
solution 1.
(Write directly to env. in java app.)
java:
...
setenv('ret', somefloatvalue);
...
exit..
c++:
system("java -jar test.jar text1 text2")
...
getenv("ret")
(I haven't test it, but important here is the context, does system creates another shell (console),
if yes, you'll not see those envs, therefore some other spawn method is necessary)
CreateProcess() on windows
fork() on linux.
There are also more complex solutions,
send some JASON's through the sockets.... etc.
Write to text file in java, read in
c++.
MPI...
extreme in this case CORBA ;)

Related

Get same JAVA compilation error as in PowerShell or CMD in Visual Studio Code

I'm on latest Windows 10. I have JDK 15. Latest Visual Studio Code (System). In VS Code, I have half of the Java Extension Pack Installed, i.e Language Support for Java (Red Hat) | Debugger for Java (Microsoft) | Visual Studio IntelliCode (Microsoft). So I did that to just get that run button on the top right (the default installed VS Code didn't have that run button for JAVA programs), below the close button, to that I can run the JAVA programs inside the VS Code. I didn't wanna go out to the directory then open Power Shell or CMD and then write java filename.java and run the program...
Now the issue is that when I click the run button, I think, a Power Shell is opened inside the VS Code and then something other than "java FileName.java" is being written. Because of that I can't really see what the compilation error is. I can only see the line number where the problem is, not actually the solution for that. || If I run the same in the PowerShell outside the VS Code with this "java FileName.java", I can see that there is some issue at x line and also the solution for the same.
So I wanted to know if there is any way to get this type of output inside the Visual Studio Code.
Or if there is any way that Instead of writing a lot of thing like this, we can simple tell the Visual Studio Code to run "java fileName.java" inside VS Code when I click the Run Button at the top.
EDIT:
The Code that I'm running is this one.....
File Name - test.java
import java.io.*;
public class SOPFileTest{
public static void main(String arr[]){
try{
// Creating a File object that represents the disk file.
PrintStream o = new PrintStream(new File("A.txt"));
// Store current System.out before assigning a new value
PrintStream console = System.out;
// Assign o to output stream
System.setOut(o);
System.out.println("Test 1");
// Use stored value for output stream
System.setOut(console);
System.out.println("Test 2");
}
catch(Exception e){
System.out.println(e.getMessage());
}
}
Now I've noticed somethings, they are:
-When (FileName == Class Name)
---Then (VS Code)
-----Prints the Last System.out.println in the console
-----A.txt is not created / written inside
---Then (Powershell)
-----Prints the Last System.out.println in the console
-----A.txt is created and/or written inside
-When (FileName != Class Name)
---Then (VS Code)
-----shows the error same as the image that I included above.
---Then (Powershell)
-----Prints the Last System.out.println in the console
-----A.txt is created and/or written inside
So powershell works as I intend it would, the VS Code isn't...
If the filename is different from ClassName, java extension will detect it and throws probelms, which is build failed and you can choose if continue:
If you choose proceed, there should be:
[UPDATE -- Screenshot in Powershell:]
It's about the same as problems shown in VS Code.
Java extension requires class must be defined in its own file, so filename should be as the same as ClassName, then everything works well, no matter in integrated Terminal in VS Code, or in the PowerShell outside VS Code:
So I wanted to know if there is any way to get this type of output
inside the Visual Studio Code.
Keeping the filename and classname same makes sure it could be built and compiled successfully, which is the first step.
And the text file should be generated in current working directory, check it in your file explorer.

Linux, JNA: UnsatisfiedLinkError on liblo second method call

I like to control 'sooperlooper' from java, a sound looper. This uses the OSC protocol. First try was the Java OSC lib, but this doesn't do anything. Now I'm trying JNA to wrap liblo.so
The program I'm trying to replicate in JAVA is very simple (of course with different commands from "record"):
static lo_address addr;
int main(int argc, char *argv[])
{
addr = lo_address_new(<IP>, "9951");
lo_send(addr, "/sl/-1/down", "s", "record");
}
The C declaration of the failing method is (https://github.com/radarsat1/liblo/blob/master/lo/lo.h.in):
int lo_send(lo_address targ, const char *path, const char *type, ...);
If I understand correctly, the lo_address is some void pointer type declared elsewhere.
My library interface is:
public interface LibLo extends Library {
Pointer lo_address_new(String host, String port);
int lo_send(Pointer address, String command, String a, String... params);
}
And my caller code is this:
System.setProperty("jna.debug_load", "true");
System.setProperty("jna.debug_load.jna", "true");
LibLo libLo = Native.loadLibrary("liblo", LibLo.class);
Pointer pointer = libLo.lo_address_new(<IP>, "9951");
libLo.lo_send(pointer, "/sl/-1/down","s", "record");
It perfectly gets through the lo_address_new call. 'pointer' does have some value. I think my arguments are correct.
And I discovered even with incorrect arguments, it gets past the lo_address_new call.
My stdout is:
...
Found library 'liblo' at /usr/lib/x86_64-linux-gnu/liblo.so.7.3.0
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'lo_send': /usr/lib/x86_64-linux-gnu/liblo.so.7.3.0: undefined symbol: lo_send
at com.sun.jna.Function.<init>(Function.java:245)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:566)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:542)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:528)
at com.sun.jna.Library$Handler.invoke(Library.java:228)
at com.sun.proxy.$Proxy0.lo_send(Unknown Source)
at nl.ronaldteune.coverdownloader.Main.main(Main.java:30)
Other questions about UnsatisfiedLinkError point to more thorough problems. I can't find 'lo_send' when opening the lib with vim, I can find lo_send_message though - but it's more low level. However, I think my C program is using the same lib (compiled with -llo) and it doesn't have problems to run.
So... I'm stuck. Anyone know how I can debug further?
You can't map lo_send() to JNA (and it doesn't appear in your vim output) because it's a macro:
#define lo_send(targ, path, types...) \
lo_send_internal(targ, __FILE__, __LINE__, path, types, \
LO_MARKER_A, LO_MARKER_B)
You could, in theory, map lo_send_internal() but the source code comments for it say:
/* Don't call lo_send_internal directly, use lo_send, a macro wrapping this
* function with appropriate values for file and line */
Which makes sense as it needs to know the source code __FILE__ and __LINE__ number at compile time, and any hack you'd make in JNA for these values would have to assume you have the correct source code used to compile your binary .so. You'd also need the markers but they are at least constants, amusing words spelled out in hex code.
You could probably just toss in dummy values for the file and line to make your code work, but otherwise, your C wrapper function calling lo_send() looks like the best workaround in this case.
OK, I worked around it... With a wrapper lib:
#include <lo/lo.h>
static lo_address addr;
lo_address slGetAddress() {
return lo_address_new("IP", "9951");
}
void slSendFull(lo_address addr, const char *command) {
lo_send(addr, "/sl/-1/down", "s", command);
}
void slSendSimple(const char *command) {
addr = slGetAddress();
lo_send(addr, "/sl/-1/down", "s", command);
}
and this compile script:
#!/bin/bash
# sudo ln -s /usr/lib/arm-linux-gnueabihf/liblo.so.7 /usr/local/lib/liblo.so
# sudo ln -s /usr/lib/x86_64-linux-gnu/liblo.so.7 /usr/local/lib/liblo.so
gcc -c -Wall -O2 -fPIC lowrapper.c -llo
ld -shared lowrapper.o /usr/local/lib/liblo.so -o lowrapper.so
sudo cp lowrapper.so /usr/local/lib/
It's working now. Still interested in a real answer, but not in a hurry for that anymore :)

Display Java console output in R using rJava

I have created the following Java class and saved it as Test.java, then compiled into Test.class on the command line using javac Test.java:
public class Test {
public Test() {
}
public double power(double number) {
System.out.println("calculating...");
return number * number;
}
}
Furthermore, I have created the following R script and saved it as test.R:
library("rJava")
.jinit(classpath = getwd())
test <- .jnew("Test")
.jcall(test, "D", "power", 3)
When I execute it, for example using R CMD BATCH test.R on the command line, I get the following output, which is what I want:
calculating...
[1] 9
However, when I wrap this script in a Markdown document and compile it using knitr, I lose the message that is printed about the calculation taking place. For example, I save the following script in test.Rmd and compile it using RStudio:
```{r echo=TRUE, warning=TRUE, results='show', message=TRUE}
library("rJava")
.jinit(classpath = getwd())
test <- .jnew("Test")
.jcall(test, "D", "power", 3)
```
This only returns the following output, without the message:
## [1] 9
I read somewhere that the reason is that System.out.println in Java writes to stdout, and whether this is shown in the R console or not depends on the interpreter. For example, the output is shown on Unix systems but not on Windows or in knitr.
My questions:
Is the above interpretation correct?
How can I reliably capture or display the output of System.out.println in R, irrespective of operating system or interpreter?
If that's not possible, what is a better way of designing status messages about the current calculations and progress in Java, such that R can display these messages?
Thanks!
I'll take a stab at answering my own question... Looks like the RJava folks actually offer a built-in solution (thanks Simon Urbanek if you read this). On the side of the Java code, there is the LGPL-licensed JRI.jar, which is delivered with rJava (look at the jri sub-directory in the rJava package directory in your local R library path) and which can be copied/extracted into the Java library path. It's only 82kb, so fairly light-weight.
JRI offers a replacement of the default print stream in Java. Essentially, you redirect the system output into an RConsoleOutputStream provided by JRI. The code in my question above can be modified as follows to print to the R console instead of stdout.
import java.io.PrintStream;
import org.rosuda.JRI.RConsoleOutputStream;
import org.rosuda.JRI.Rengine;
public class Test {
public Test() {
Rengine r = new Rengine();
RConsoleOutputStream rs = new RConsoleOutputStream(r, 0);
System.setOut(new PrintStream(rs));
}
public double power(double number) {
System.out.println("calculating...");
return number * number;
}
}

.exe made from C++ works on command line but not from Java

I have a .exe which mutes my windows computer. It is compiled from a C++ program. When I run this .exe from the command line, it works great, muting or unmuting my computer. However, I'm trying to run this from a Java program and I get no error, but it also doesn't actually run, or at least not properly since the volume is not toggled. I've been poking around to see what it could be and nothing obvious since the call to execute the .exe returns 0 and no errors.
Any thoughts would be helpful. Thank you.
Here's the c++ code which is compiled into "mute.exe":
void VolumeControl::mute() {
HWND hwnd = GetConsoleWindow();
SendMessage(hwnd, WM_APPCOMMAND, (WPARAM)hwnd, APPCOMMAND_VOLUME_MUTE << 16);
}
Here's the java code that calls it (I've tried using runtime exec as well as process builder):
Process p = Runtime.getRuntime().exec("mute.exe");
int exitVal = p.waitFor();
System.out.println(exitVal);
//Process process = new ProcessBuilder("mute.exe", "-u").start();
//Runtime rt = Runtime.getRuntime() ;
//rt.exec("mute.exe");

C++ save & import external executable result without writing on disk

In a C++ code run in Linux, I need to call an external java executable "EXEC.JAR", make him save a result file "JAVA_RES.txt", and then import this file in C++ to parse some values.
The only way I found till now to do that is calling the system function
system("java -jar EXEC.JAR --input " + someInputs + " > JAVA_RES.txt");
The very big problem of this implementation is that writing this file on the hard disk (or in a network shared filesystem as in my case...) makes the implementation really slow (I have to call this function A LOT of times).
Is there any better way to do that? Is there a way to save the result of EXEC.JAR in the RAM memory and then import it in C++?
Yes you can try using use popen() this way:
int main(void) {
FILE *in;
extern FILE *popen();
char buff[512];
char s[1024]; //someInput
if(!(in = popen("java -jar EXEC.JAR --input " + s, "r"))){
exit(1);
}
while(fgets(buff, sizeof(buff), in)!=NULL){
printf("%s", buff);
}
pclose(in);
}

Categories