Read c++ console output from method call using Java - java

Currently, I am trying to read the console output of my program when there is a method call. How it works is, my Java program calls the JNI wrapper to invoke the C++ method call. My C++ is using std::cout. The payload.invoke will invoke my c++ library API. Inside the c++ API there are a few cout statements. That is the statement I want to read it as a variable in Java.
The current PrintStream only supports out, print, println and printf.Each time when there is a method call, there are bunch of logs being printed out in command prompt. Now, I would like my java program to read those output which my C++ prints out.
This is my current Java code:
public void execute() {
try {
Matcher m = Pattern.compile("([^()]*)[(]([^()]*)[)]").matcher(getPayloadString());
m.find();
boolean passed;
if (m.group(2).isEmpty()) {
// this is where it invoke the method
passed = (boolean) payload.invoke(testcase);
System.out.println("Boolean is: " + passed + "\n");
}else {
passed = (boolean) payload.invoke(testcase, ObjectCreator.convertParameters(m.group(2)));
System.out.println("Boolean2 is: " + passed + "\n");
}
String output = passed ? "PASS" : "FAIL";
// I want to use the console output string variable here -> xxxx
TestCase.printResult(payload.getName(), output, m.group(2), xxxx, "");
} catch (Exception ex) {
ex.printStackTrace();
}
}
Are there any ways to do it? Previously I tried using one of the tutorial from here. but that seems not working. Can someone help me out with this please. Thanks in advance.

If you have full control of the .cpp codebase it is possible for you to change the std::cout to become a ostream& instead.
By referencing a base class you can easily switch the implementation.
Do a JNI-Stream whichh extends the ostream& and just overwrite the operators you need to send JNI wrapped callbacks to java.
Then depending on if you run native or Java style use your JNI-Stream instead of the std::cout.
I would do something as seen in the link below to package and send the data to Java:
JNI - How to callback from C++ or C to Java?
that is my 2 cents.

Read carefully the JNI tutorial.
https://www.baeldung.com/jni
Follow the tutorial.
Basically you need to create a java class with a static block to load the C++ library:
static {
System.loadLibrary("native");
}
Then you can create your own static java method and invoke a method on the library.
If what you need is read the output from a system call, it's a different matter.
This can help you:
Java Runtime.getRuntime(): getting output from executing a command line program

Related

JNI code fails to call C function on Linux but not Windows

I have the following Java code generated using SWIG. Although SWIG was used to generate the code knowledge of SWIG should not be needed to understand this question
User facing Java code:
public class UuidUtil implements OCUuidUtilConstants {
public static Uuid generateUuid() {
long cPtr = UuidUtilJNI.generateUuid();
return (cPtr == 0) ? null : new Uuid(cPtr, true);
}
}
The UuidUtilJNI.generateUuid() is defined as follows
Java code calling JNI code
public class UuidUtilJNI {
public final static native long generateUuid();
}
The SWIG generated JNI C wrapper code uuid_wrap.c
uuid_t * jni_gen_uuid()
{
printf("Inside jni_gen_uuid\n");
uuid_t *value = (uuid_t *)malloc(sizeof(uuid_t));
printf("Calling gen_uuid\n");
gen_uuid(value);
return value;
}
SWIGEXPORT jlong JNICALL Java_UuidUtilJNI_generateUuid(JNIEnv *jenv, jclass jcls) {
jlong jresult = 0 ;
uuid_t *result = 0 ;
(void)jenv;
(void)jcls;
result = (uuid_t *)jni_gen_uuid();
*(uuid_t **)&jresult = result;
return jresult;
}
partial C code for gen_uuid(uuid_t *uuid) function uuid.c
void gen_uuid(uuid_t *uuid)
{
printf("Inside gen_uuid\n");
/* code to set the uuid to type 4 UUID according to RFC4122 */
}
I am testing it as follows:
#Test
public void generateAndConvert() {
Uuid testUuid = UuidUtil.generateUuid();
assertNotNull(testUuid);
// other test code left out for readability
}
When the test is run on Windows the code works as expected.
When I try and run the same code on Linux the test hangs.
It prints 2 of the 3 print staments found in the code.
Inside jni_gen_uuid
Calling gen_uuid
the line Inside gen_uuid is never called when the test is run on a Linux machine (Fedora 30).
My first thought was that there was some sort of mismatch in the output of the object files causing the wrapper code to fail when calling the uuid code. I have compared the build flags used to build uuid.c and uuid_wrap.c code and they are using the same flags with the exception that some of the build warning are shut off for the wrapper code because its generated by a tool and not intended to
be modified by me.
I don't really know where else to look.
I have checked the uuid.o file using nm and objdump as best I can tell it has the gen_uuid symbol.
I have not been able to properly attach gdb to the running sample so not sure if that would provide any useful information.
Any suggestions that may help find the issue?
Unfortunately this solution was very specific to my code.
When I wrote that the print statement
printf("Inside gen_uuid\n");
/* code to set the uuid to type 4 UUID according to RFC4122 */
was never called I was wrong. The text was just not flushed to the screen. Adding fflush(stdout); after the print statement would have shown that indeed the gen_uuid function was being called.
As noted in the question this code generates a type 4 UUID which is a random UUID.
The code that generates random numbers is OS specific. Before the random number can be read the random number generator must be initialized. On Linux this is done by grabbing a file descriptor to /dev/urandom on Windows it is done by seeding srand() function.
Linux would segfault when generating the random number if random_init was not called. Windows on the other hand would produce a number even if it were not seeded.
The solution was to call randomInit() before calling generateUuid() in the unit test.
If you are a developer exploring a similar failure and are using printf debugging to check if a line of code was reached then make sure the print statement is flushed to the screen before concluding that a line of code is not being reached.

NullPointerException while using jruby

I embed jruby script engine into my java program by using javax.script.ScriptEngineManager
I made some jruby code that end with do ~ end block,
after running all code, NullPointerException occured.
but code ends with any other statement, no exception occurs.
version : 1.7.19
Caused by: java.lang.NullPointerException
at org.jruby.embed.variable.Argv.updateARGV(Argv.java:169)
at org.jruby.embed.variable.Argv.retrieve(Argv.java:158)
at org.jruby.embed.variable.VariableInterceptor.retrieve(VariableInterceptor.java:154)
at org.jruby.embed.internal.BiVariableMap.retrieve(BiVariableMap.java:378)
at org.jruby.embed.internal.EmbedEvalUnitImpl.run(EmbedEvalUnitImpl.java:124)
in ARGV.java updateARGV
if (vars.containsKey((Object)name)) {
var = vars.getVariable((RubyObject)receiver.getRuntime().getTopSelf(), name);
var.setRubyObject(argv);
vars.getVariable returned null because of isReceiverIdentical return false
in BiVariableMap.java
if (var.isReceiverIdentical(receiver)) {
return var;
}
In isReceiverIdentical, this method just compare receiver with BiVariable's receiver usgin '=='.
Is this jruby bug? Or do I have to do something for this?
If you need more information about this problem, plz comment it!
I got ScriptEngine(engine) from ScriptEngineManager and set some java instance and method like this
engine.put("this", console);
engine.eval("$command = $this.java_method :command, [java.lang.String]");
here is my test ruby code. result and tab is java object
that has some method return String and list.
result = $command.call "something to pass"
puts result.getMessage
tabular = result.getData
tabular.each do |tab|
rows = tab.getRows
rows.each do |row|
puts row
end
puts tab.getColumnNames
end
I had created ruby type object in my java code by creating new Ruby object...
This causes checking fail in updateARGV because a receiver that register variable in BiVariableMap and another receiver that update variable are different.
So, I got a Ruby object from new ScriptingContainer(from it we can always get a same Ruby object if local context is singleton) and used it to create new ruby type object in my java code.
Reference: https://github.com/jruby/jruby/wiki/RedBridge#Singleton

Supressing console (disp) output for compiled MATLAB > Java program (using MATLAB Compiler)

Edit 2 After recieving a response from Mathworks support I've answered the question myself. In brief, there is an options class MWComponentOptions that is passed to the exported class when instantiated. This can, among other things, specify unique print streams for error output and regular output (i.e. from disp()-liked functions). Thanks for all the responses none the less :)
====================================================================
Just a quick question - is there any way to prevent MATLAB code from outputting to the Java console with disp (and similar) functions once compiled? What is useful debugging information in MATLAB quickly becomes annoying extra text in the Java logs.
The compilation tool I'm using is MATLAB Compiler (which I think is not the same as MATLAB Builder JA, but I might be wrong). I can't find any good documentation on the mcc command so am not sure if there are any options for this.
Of course if this is impossible and a direct consequence of the compiler converting all MATLAB code to its Java equivalent then that's completely understandable.
Thanks in advance
Edit This will also be useful to handle error reporting on the Java side alone - currently all MATLAB errors are sent to the console regardless of whether they are caught or not.
The isdeployed function returns true if run in a deployed application (with e.g. MATLAB Compiler or Builder JA) and false when running in live MATLAB.
You can surround your disp statements with an if isdeployed block.
I heard back from a request to Mathworks support, and they provided the following solution:
When creating whatever class has been exported, you can specify an MWComponentOptions object. This is poorly documented in R2012b, but for what I wanted the following example would work:
MWComponentOptions options = new MWComponentOptions();
PrintStream o = new PrintStream(new File("MATLAB log.log"));
options.setPrintStream(o); // send all standard dips() output to a log file
// the following ignores all error output (this will be caught by Java exception handling anyway)
options.setErrorStream((java.io.PrintStream)null);
// instantiate and use the exported class
myClass obj = new myClass(options);
obj.myMatlabFunction();
// etc...
Update
In case anyone does want to suppress all output, casing null to java.io.PrintStream ended up causing a NullPointerException in deployment. A better way to suppress all output is use to create a dummy print stream, something like:
PrintStream dummy = new PrintStream(new OutputStream() {
public void close() {}
public void flush() {}
public void write(byte[] b) {}
public void write(byte[] b, int off, int len) {}
public void write(int b) {}
} );
Then use
options.setErrorStream(dummy);
Hope this helps :)
Another possible hack if you have a stand-alone application and don't want to bother with classes at all:
Use evalc and deploy your func name during compile:
function my_wrap()
evalc('my_orig_func(''input_var'')');
end
And compile like
mcc -m my_wrap my_orig_func <...>
Well, it is obviously yet another hack.

tuProlog unknown behavior

I'm using tuProlog to integrate Prolog with Java, to do so I have defined a prolog.pl file with the following code:
go:-write('hello world!'),nl.
Then, in my Java project I Have the Main Class that invokes this:
Prolog engine = new Prolog();
Theory theory = new Theory(new FileInputStream("prolog.pl"));
try {
engine.setTheory(theory);
} catch (InvalidTheoryException ex) {
}
SolveInfo solution = engine.solve("go.");
if (solution.isSuccess()) {
System.out.println(solution.getSolution());
}
This code should output 'hello world', however, it outputs 'go', any ideas of why this behavior?
Finally found that the behavior was not erratic at all :)
The solution is to add this code just before calling the Solve Method.
engine.addOutputListener(new OutputListener() {
#Override
public void onOutput(OutputEvent e) {
finalResult += e.getMsg();
}
});
finalResult is just a Global variable that contains the returned String produced by Prolog Write instruction.
Your solution it's (correctly) the succeded Prolog query (go/0), what you expect ('hello world!') it's the output of a builtin, as such you should inspect the 'stdout' of your Java engine.
Otherwise, code your program to 'return' info in variables.
go(X) :- X = 'hello world!'.
Then tuProlog will provide the methods to access instanced variables.
I don't know about tuProlog/Java, but when calling Swi-Prolog from PHP, I must put 'halt' as the final statement of the predicate to tell Prolog to exit and return control back to php.
go:-write('hello world!'),nl, halt.

how to pass java output as a matlab variable?

I have written a Java program which is invoked using system() function, thus it runs on the command window of Matlab. Now I want to know if there's another way to run a Java program other than running it on command window? Can it be run on any user made GUI in Matlab? Another problem is, I want to know if my program has some string value as output, which is generally displayed on command window, how can i store it in variable in Matlab?
Hope to hear from you very soon.
The Hello World solution by The MathWorks provides some insights on how to run a simple 'Hello World' java application inside MATLAB. You may change the Java code a bit, in order to have a method that returns a String.
public class HelloWorld
{
public String hello()
{
String helloWorld = "Hello World!";
return helloWorld;
}
}
Once this simple class is compiled and on the MATLAB JVM classpath create an instance and invoke the method with the following two commands.
o = HelloWorld
output = o.hello;
The String returned by the HelloWorld instance is assigned to the MATLAB variable output.
There is no need for a system command with Java code in MATLAB. You have direct access to the JVM from inside MATLAB. For an application with a complex GUI, break out to Java.
Undocumented Java is a valuable source on MATLAB, Java and GUIs.
Yes the classpath set is correct.
I modified the code, using it without main..
class HelloWorld
{
public String Hello()
{
String helloWorld="Hello World!";
return helloWorld;
}
}
Now, as per guided i try to create instance obj in Matlab, with following command:
o = HelloWorld;
Here I get following err:
??? No constructor 'HelloWorld' with
matching signature found.
The next command indicated it this:
output = o.hello;
which wouldnt work unless instance is created.

Categories