I want to pass String containing contents of xml file to native function using JNA .But somehow it is giving me problems. The program goes into infinite loop and does not get terminated. The same thing is working when I am trying to access DLL through C.
This is how my code looks like -
Native side --
Class ABC{
...
long t = processValues(const * str1 ,char** output);
...}
JNA interface looks llke this -
public interface Add extends Library
{
Add INSTANCE = (Add) Native.loadLibrary("add", Add.class);
...
NativeLong processValues(String str1,PointerByReference output);
...}
main method in java class is as follows -
public static void main(String args[]){
Add lib = Add.INSTANCE;
PointerByReference ptrRef = new PointerByReference();
String strBuffer = "<?xml version= \"1.0\" ?><NRECORD> <SUBRECORD><ITEM1> <NAME> pqr</NAME> <MDATE>10/12/2012</MDATE><ENGINEER>TMAY</ENGINEER></ITEM1></SUBRECORD></NRECORD> "
Nativelong p = lib.processValues(strBuffer,ptrRef);
}
The program goes into infinite loop and never get terminated. DLL uses recursive function to parse input xml string, I think this is where problem lies. (I am using third party dll so cant access code.) But function processValues() get executed successfully when same dll is accessed through C.(with same input parameters) My questions are
is this right way to pass xml contents as string?
Is there any way by which I can get event logs how the dll functions are getting called.
Thanks in advance.
Related
I have implemented a method that generates Java code:
public static String generate() { ... }
It returns Java code as a String, i.e. I might get
"public class X { public static String x() { return \"x\"; } }"
as a value returned by generate. Now, I am in a JShell Tool (JEP-222) session, and I can call generate, but I fail to load the result of generate into JShell itself.
Ideally I'd like to achieve the following
jshell> eval(generate());
| created class X
jshell> X.x();
$2 ==> "x"
In the above (hypothetical) JShell sesssion, eval is the function that I am looking for.
Possible solutions I already tried:
I know that this would be possible by calling JShell#eval but I failed to obtain the JShell object that represents the currently running JShell.
It might be that there is some facility in JShell that allows lifting a String to a Snippet. I couldn't find something like that, but if there is, it might be helpful.
I know that I can /open a file, so it might be possible to write the String to a file and then open/load it. However this is a two-step process, and I would prefer to have a solution that is simpler.
I use rJava to call a java code from R, trying to call an algorithm from SPMF tool. I tried to use a wrapper function as in this question, but this did not work with the SPMF code.
this is my R code:
library(rJava)
.jinit()
.jaddClassPath ( "C:/mydrive/eclipse-workspace/myfile/src")
print(.jclassPath())
obj <- .jnew("AlgoFPGrowth_Strings")
s <- .jcall(obj, returnSig= "V", method="runAlgorithm",
"input.csv","output.txt") , 0.4 )
it gives me error ,method runAlgorithm with signature (D)V not found
this is the main in java:
public static void main(String[] args) throws Exception {
AlgoFPGrowth_Strings fpwindow=new AlgoFPGrowth_Strings();
String input="input.csv";
String output="output.txt";
double minsupp = 0.4;
fpwindow.runAlgorithm( input, output, minsupp);
fpwindow.printStats();
}
I tried to change returnSig value into S and Ljava/lang/String; but I got the same error, could not find the method
when I apply the code on different java code with simple method it works, is there any idea how can I change my code?
Try the below methods,
Change your jclassPath, where you directly specify the complete pathname of your jar file including the jar name, say /home/user/mypath/myclass_name.jar
Or, you can unzip your jar file in a folder and refer to that path in your jclassPath.
If, the above does not work,
Try to write the 'runAlgorithm' method in the same class where you are calling. I have faced issues with calling external libraries/classes.
Situation: I have a library of JNI files, the library is comprised of several functions that are called by the main header file in that JNI library (i.e., code1.h). I have a Java file (i.e., code2.java) that I want to pass to and from JNI header file (code1.h). I created a source code for the (code1.h) called (code1.c).
My question is: Does (code1.h), (code1.c), and (code2.java) have to be the same name for the communication between the JNI and the java?
EDIT: So (code1.h), (code1.c), and (code1.java) all have to be the same name in order for the (code1.java) to pass strings to/from (code1.c)/(code1.h)? And it is not possible to have (code2.java) pass strings to/from (code1.c)/(code1.h) because they are not named the same, is this correct?
For instance,
public class code1 { /*this is code2.java, but should the name be changed to (code1.java) to match that of the JNI?*/
static {
System.loadLibrary("myjni");
}
to pass strings to code1.h/code1.c
This will be compiled for android using Linux Debian"Wheezy" and Eclipse with Android SDK and NDK
While Java requires a match between compilation unit name (SomeClass.java being the name and public class SomeClass{ being the declaration, C does not require this.
You may name the C source and header files as you see fit as long as the function names/exported symbol names match the name of the native method on the java side. For example:
//JavaClass.java
public class JavaClass{
public native String getAString(String in);
}
And header would be:
// any name
JNIEXPORT jstring JNICALL
Java_JavaClass_getAString(JNIEnv *, jobject, jstring);
with matching C files. You could name this header catsMakeTheWorldGoRound.h for all Java cares.
Here is an example of what your "JNI object" should look like.
//In my experience, it is better to put the JNI object into a separate package.
package org.example;
public class Code1
{
static
{
// On a Linux system, the actual name of the library
// is prefixed with "lib" and suffixed with ".so"
// -- e.g. "myjni-java.so"
// Windows looks for "myjni-java.dll"
//
// On a Windows system, we also need to load the prequisite
// libraries first. (Linux loaders do this automatically).
//
String osname = System.getProperty("os.name");
if (osname.indexOf("win") > -1 || osname.indexOf("Win") > -1)
{
System.loadLibrary("myjni");
}
System.loadLibrary("myjni-java");
}
// Now we declare the C functions which we will use in our Java code.
public static native void foo(int bar);
public static native int bar(String foo);
//...
}
Given that you have compiled your JNI library correctly, you can then call the C functions from other Java classes like this:
//Again, in my experience, it is better to explicitly give the package name here.
org.example.Code1 Code1= new org.example.Code1();
Code1.foo(123);
int a= Code1.bar("Hello C function from Java function!");
Does this help you with your question? (I am not an expert in JNI, so I might not be able to help further.)
The static method main, which receives an array of strings. The array should have two elements: the path where the files are located (at index 0), and the name of the files to process (at index 1). For example, if the name was “Walmart” then the program should use “Walmart.cmd” (from which it will read commands) and “Walmart.pro” (from which it will read/write products).
I don't want anyone to write the code for me because this is something I need to learn. However I've been reading this through and the wording is confusing. If someone could help me understand what it wants from me through pseudo-code or an algorithm it would be greatly appreciated.
Where I'm confused is how to initialize arg[0] and arg[1] and exactly
what they are being initialized to.
The main method's String array input argument consists of whatever String arguments you pass to the program's main method when you run the program. For example, here is a simple program that loops over args and prints a nice message with each argument's index and value on a separate line:
package com.example;
public class MainExample {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.printf("args[%d]=%s\n", i, args[i]);
}
}
}
Once you've compiled the program, you can run it on the command-line and pass it some arguments:
java -cp . com.example.MainExample eh? be sea 1 2 3 "multiple words"
Output:
args[0]=eh?
args[1]=be
args[2]=sea
args[3]=1
args[4]=2
args[5]=3
args[6]=multiple words
So lets explain to you
Create a class Inventory : if you don't know how to create a class google it just as is
The static method main: Every executable class in java (at least from the console) has the main method you should google java main method and propably in the same place you find it you will see the default arguments that it receives
When you learn about the default arguments of method main you will undertand about the 'args' that has to be on it
You will have t study the class String google it "java String class"
You will have to study the class File google it "java File class"
At the end everything else would be just logic and I beleave you have learned some at this point.
public class Inventory { // class inventory
public static void main(String[] args) // main method
{
if(args.length==2){ // check if args contains two elements
String filePath = args[0];
String fileName = args[1];
filePath+= System.getProperty("file.separator")+fileName;
File fileCMD = new File(filePath+".cmd");
//fileCMD.createNewFile();
File filePRO =new File(filePath+".pro");
//filePRO.createNewFile();
}
else {
//write the code to print the message Usage: java Inventory Incorrect number of parameters for a while and exit the program.
}
}
This is what I've understood. Basically you have to write a program to create two files, one called fileName.cmd and the other fileName.pro. You have to construct the path of the files using the arguments (input parameters of the main method) and system's file separator. If the arguments don't have two elements you have to print the 'invalid' message. That's it.
Where I'm confused is how to initialize arg[0] and arg[1] and exactly
what they are being initialized to.
You have to use command line to pass the arguments and launch the program , something like the following code in cmd or terminal:
java inventory thePath theFileName
That's how it get initialized.
The "Path of the running EXE" is well defined for Windows Applications written in C#, C++, VB, etc.
-
Java Applications on Windows are not "EXE-Applications" but a class-file or a jar-file is started rather than an EXE-file.
So for java Applications the term "ExePath" should be translated to "MainClassPath" or to "JarPath" resp.
-
In some cases a programmer needs to know the physical Path of the Application's jar or MainClass.
(e.g. when you develop a large project both in java and in c# with identical classes and identical methods)
-
thanks to other stackoverflow users this statement does the job:
String exePath = URLDecoder.decode(this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath(), "UTF-8")
and now comes my question:
If I put the same code into any helper/utils jar-library then it will return the path of the helperlib.jar, it will NOT return the path of my MainClass/AppJar !
-
So the final getExePath() helper method should look something like:
return(URLDecoder.decode(Thread.currentThread().getStartingThread().getMainClass().getProtectionDomain().getCodeSource().getLocation().getPath(), "UTF-8"));
(if there only were methods like getStartingThread() and getMainClass() in java ...)
-
please, point me to the final solution, how can I implement these steps:
get the starting Thread
get the Main Class of the starting Thread
get the Path of the Main Class
if I get you right, just put the method with a parameter of the desired class into your helperlib-class ...
e.g.:
public static String getExePath(Object main) {
String path = "";
try {
path = URLDecoder.decode(main.getClass().getProtectionDomain().getCodeSource().getLocation().getPath(), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return path;
}
then you can call it e.g. from inside your main-jar with the parameter 'this' ...
System.out.println("AppPath:\n" + helperlib.getExePath(this));
... and you got the path of the class specified in you parameter
hope it helps and sorry for my bad english ... ;)