Short Question:
Passing a parameter from C++/C JNI to Java method who supposed to modify. Will the modified result available back in C/C++ JNI? Is there any way to do it? Other than return and a callback from java?
Continue if above is not clear:
Calling below function from C/C++ JNI with jcharArray. Below Java function is supposed to work on passed char array and store the final result in same. So that modified result will be available back in C/C++ JNI.
I have java function accepting a char[] like below
void GetName(char[] s)
{
String t = "Test";
// Work on t and store the result in s
s = t.toCharArray();
}
How I can achieve this ... I am getting all the examples that are another way around like Java calling C/C++.
Java only supports pass by value. If you want to return a reference you need to either
a) return it
char[] getName();
b) Pass a mutable object to reference it
void getName(char[][] nameArray) {
nameArray[0] = t.toCharArray();
}
c) Pass a call back
void getName(Consumer<char[]> listener) {
listener.accept(t.toCharArray());
}
So for my scenario, I modified the declaration like below
void GetName(char[] s) to void GetName(PersonName obj)
So now, I am creating an object of PersonName in JNI and passing that as a parameter to the java function. Later I am using the same object to call getter methods of the PersonName class to get the values char[] RetriveName();
I also found that using jfield also you can get the values of the class data members but then those members should be public
Related
I started with java a couple of weeks ago. Before that i had multiple years working with c/c++ on embedded targets and with c# with UI Stuff on Win PCs.
I got this very simple example:
public class StreamProcessing {
public static void main(String[] args) {
Stream stream = new Stream(); //after this line: Stream string empty
StreamFiller.fillStream(stream); //after this line: Stream string not empty any more
StreamPrinter.printStream(stream);
}
}
I'd expect that whatever StreamFiller.fillStream() does, the argument is copied. However it looks like fillStream is modifying the actual stream object itself.
The Stream class basically contains a string
public class Stream {
private String content = "";
int index = 0;
public char readChar() {
if (index < content.length()) {
return content.charAt(index++);
} else {
return 0;
}
}
public void writeString(String str) {
content += str;
}
}
The Streamfiller should modify it's stream copy but not the original reference
public class StreamFiller {
public static void fillStream( Stream stream ) {
stream.writeString( "This is a" );
stream.writeString( " stream." );
}
}
Please correct me if I'm wrong, but since the actual text of the string class is allocated on the heap, both the StreamProcessing () Stream object and the (supposed copied) local object of fillStream() point to the same address on the heap (yeah i now it's not an actual memory address like in c/c++ but some unique object identifier)
So is my assumption correct? Non trivial objects (aka objects allocated on the heap) are passed by reference?
thx for your help :)
The Java language does not let you make heap / stack distinction in your code the way C and C++ do.
Instead, it divides all data types in to two groups:
Primitive types:
These are simple built in numerical types such as int, double or boolean (not a numerical type in Java).
Note that String is not such a type!
Object types:
If it is a class, it is an object type. This goes for built in types such as String and for user defined types such as your Stream class.
For these types, all you ever see is a reference, whether you are looking at a local variable, class member, instance member, or function parameter.
Lets look at a simple example:
public class A {
public int a;
public static void main(String [] args) {
A var1 = new A();
A var2 = var1;
var1.a = 42;
System.out.println("var2.a = " + var2.a);
}
}
If you compile and run this example it will print 42.
In C++ the line A var2 = var1; would have invoked a copy constructor and created a new object but in Java there is no such thing. If you want a copy, you need to invoke clone method explicitly.
What is held in var1 and copied to var2 is just a reference.
So both vars "point" to the same object.
And again - it does not matter if the class is trivial or not. Even if a class is completely empty, you will still only be given and work with a reference to any object of this class.
As for the primitive types mentioned earlier, Java has wrapper classes such as Integer and Boolean for them.
You might want to read about "boxing" and "unboxing".
One more thing to note is that some types are immutable - that is, they do not provide a way to change their data once created.
String in Java is an immutable type, but it is also a bit different from any other type.
It has special privileges.
While Java does not support operator overloading like C++ does, for String type the language does provide a special + operator that preforms string concatenation.
How ever, since String objects are immutable, any concatenation operation will create a brand new String object, even one like this:
String a = "Hello";
a = a + " world!";
This creates a new string "Hello world" and stores the reference to it in a, leaving the reference to old "Hello" string to be garbage collected at some future point.
Even though in Java everything is passed by value, there is a difference between how primitive data types (such as int, char and boolean) and how reference data types are passed to a method.
When passing the value of a primitive data type, this value can only be changed in the scope of the particular method. When passing the value of a reference data type, the reference will remain the same but the value will change globally (or in whatever scope the object was initialised).
See also this for more information: https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html
I was recently reading a java class where the person had created methods via IDE shortcut( extract method shortcut ). All methods had a return type of void and what was supposed to be return type was passed as input parameter for the method. Below is an example of what i'm referring to.
public void multiply(Integer first, Integer second, Integer result){
result = first * second;
}
I was wondering if the above is a good way of doing things. I personally do not like the above way of creating methods. I think the method should have been like below.
public Integer multiply(Integer first, Integer second, Integer result){
return first * second;
}
But in IntelliJ/Eclipse when we do extract method mostly creates method like above.
Can someone please let me know why IDE's usually create void method when we use the extract method shortcut and is the 1st style of method definition a good practice at all?
If the method being called isn't being assigned to a variable, Eclipse has no way to know what the return value is supposed to be.
Presumably, the original code looked something like this:
public static void main(String args[]){
Integer result = 0;
multiply(1,3,result);
}
There's no way for Eclipse to divine that multiply is supposed to return anything, so it defaults to void. If you want to infer return values, have it be assigned to a variable like so:
public static void main(String args[]){
Integer result = 0;
result = multiply(1,3,result);
}
I have a java method, like this:
public static native void receiveCallback(byte[] value1, byte[] value2);
In JNI I can reach the class and I can reach the method, but my parameter list is incorrect. I am trying to call the method like this:
jmethodID testJavaMethod = (java_environment)->GetMethodID(clazz, "receiveCallback","([B[B");
I then get a NoSuchMethod exception at runtime.
I followed multiple SO questions, including this one JNI - How to callback from C++ or C to Java?, but I'm still stuck.
Any suggestions?
Thanks.
If you want to call back into Java, the implementation must be in Java. You need
public static void receiveCallback(byte[] value1, byte[] value2) {
// do something with value1 and value2
}
And to get the id of a static method you need to use "GetStaticMethodID". Also to call it you will have to use "CallStaticVoidMethod()".
I have a C API that looks like this:
int my_function(char** assign_me_a_string);
I basically need the native code to tell me a value. If I do:
char* my_function();
It works fine. I get a String in return that I can use in Java. However I would prefer to use the first approach since all my functions returns an int by default (status value).
I have tried to use various.i and this typemap:
%apply char **STRING_ARRAY { char **assign_me_a_string }
Doing this I get a String[] generated for the Java API. Then I try to use it by:
String[] myStringToAssign = new String[1];
my_function(myStringToAssign);
But this seems to just crash.
So, is there a proper way to assign a value to a Java String from inside the C code? I am not trying to use an array, I just need to be able to dereference the char** and assign it a string in the native code that can then be used as a String object in Java.
Java String is immutable and references are passed by value so the following will not do what you think (pure Java):
// java:
void someFunction(String yourString) {yourString = "bye";}
void test() {
String test = "hi";
someFunction(test);
System.out.println(test); // prints "hi", not "bye"!
}
(For more on this, see for example Passing a String by Reference in Java?). Needless to say you can't do it using JNI either.
Look at section 24.10.5 of SWIG 2.0 docs: it shows how you could do this for char** via a typemap. However the typemap there would have to be modified to check the char* array on exit (the freearg typemap, perhaps) to replace the contents of the String[]. Your function could assume only one item.
Alternately you could wrap your Java String in a class, which will get passed by reference; however you again would have to use a typemap to copy any changes that have been made into the data member.
Probably the easiest is to provide a helper function that swaps the status code and string:
// C/C++ lib: the function you'd like to export but can't:
int my_function(char*& ) {
val = new char[20];
...put stuff in val, don't forget the terminating \0 char...
return status;
}
Create wrapper:
// SWIG .i file: an "adapter" function, Java gives you no choice:
%inline %{
char* my_function(int& err) {
char * val;
err = my_function(val);
return val;
%}
SWIG will take care of copying the char* to the returned String:
// From Java you can then do:
int status;
String result = my_function(status);
System.out.println(result);
No, Java Strings are immutable and cannot be assigned not even through JNI.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
This question may seem dumb at first, but after having worked with different person, I see everyone seems to have their own, different knowledge about it, so here's my question.
So now I'm wondering what is the best way to do it, and why ("why" is more important for me):
I'm wondering about two methods to write Java code:
Do you always pass Object or can you pass primitive data type ?
Do you call variables using this.name, name or getName() inside your class instance ?
public class MyClass {
private String someStr;
private int someNumber;
private Integer someOtherNumber; // int, Integer ? which one to choose ?
public MyClass(String someStr, int someNumber, int someOtherNumber) { // int someNumber ? Integer someNumber ? why ?
this.someStr = someStr; // Here, it's clearly this.{name} = {name} because of the variable name conflict
this.someNumber = someNumber;
this.someOtherNumber = someOtherNumber;
}
public int someMethod(boolean first) { // Boolean ? boolean ?
if (first) {
return someNumber;
} else {
return this.someOtherNumber; // this.{name} ? just {name} or even this.get{name}() or get{name}() ? (supposing getters exists)
}
}
}
I hope someone will provide me with a great explanation about which to use in order for me to write better code.
Do you always pass Object or can you pass primitive data type ?
You can't pass an Object, only a reference to an Object. You can pass primitive data.
Do you call variables using this.name, name or getName() inside your class instance ?
I don't make it more complicated than I need to, unless it's conflicts with a local variable or my getName() does something special, but that is a matter of style.
Do you always pass Object or can you pass primitive data type ?
You can pass primitives or references to objects depending on your need.
Do you call variables using this.name, name or getName() inside your
class instance ?
this is used to refer to the current object. If there are conflicting variable names and you want to distinguish between the object variable and local variable then use this.
Also you seems to be confused about primitives and Wrapper classes. Wrapper classes provides utilities methods and are of use especially working with collections.
If you need to work with the primitive data types then you should use them, e.g., int, double, char, float, etc. The only exception is String which in Java is a special class that represents a char array and also holds instance methods.
The case with Integer vs int, is when you need to use Integer methods (http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Integer.html). But if you only need a data type to hold your value then choose int.
Do you always pass Object or can you pass primitive data type ?
public int someMethod(boolean first) { // Boolean ? boolean ?
}
In the following example, you can pass boolean and Boolean with the same success. In Java this is called Autoboxing.
N.B. Be careful, because when passing an object it may be null!
Do you call variables using this.name, name or getName() inside your
class instance ?
Depends. If name is an class member variable, you can access it with name if there isn't any other variable in the current scope that has the same name. In this case you should use this.name to point exactly to the class member variable. getName() may be used, as well. It's just a matter of style.
I keep it simple. I'm using name, but if I have a local variable with the same name I must use this.name (my prefered solution) over getName().
getName() must be used if it do some logic like validation.
Do you always pass Object or can you pass primitive data type ?
It depends on your application and your needs. If you pass a reference to an object, you are able to use the methods of the related type which may be more secure and portable. Let say you are using the class Double. Double has many peer-reviewed and tested methods which may be helpful to you.If you prefer to use primitive type, double, you need to be careful in your manipulations like comparing, validating etc.
For performance issue, you may check a previous discussion below:
Why do people still use primitive types in Java?
Do you call variables using this.name, name or getName() inside your class instance ?
I prefer using this when I refer a class member because i think it will be helpful for others reading my code to understand that the variable is a class member.
Finally, whatever style you prefer, I think you should stick to it in your applications.
Do you call variables using this.name, name or getName() inside your class instance ?
It is mostly a matter of personal style and principle.
private int someOtherNumber; I almost always use int because it seems more natural to me --perhaps influenced by the C days. And, from performance and memory usage point of view using int is a better choice. As a rule of thumb, I don't use objects for primitives unless I have a good reason to.
return this.getSomeOtherNumber(); I prefer using getters/setters; since sometimes -not always- the getter method is not just a simple return statement, rather it encapsulates some logic. As a result, I don't directly access class attributes (like this.someAttr or someClass.somePublicAttr) unless it's a final attribute. Believe me, it's much safer.
Continuing 2: It may seem a bit strange but I, having a strong Lisp background, try to avoid using even getter/setter methods (class state) as much as possible and instead explicity pass the required parameters and use the methods' return values. Consider the following example:
public class C {
private int a;
private int b;
public int getA() { return a; }
public void setA(int a) { this.a = a; }
public int getB() { return a; }
public void setB(int b) { this.b = b; }
// Usual style
public void someMethod1(int x) {
mainLogic1(x);
}
private void mainLogic1(int x) {
b = a + x;
}
// My preferred style
public void someMethod2(int x) {
setB(mainLogic2(x, getA()));
}
private int mainLogic2(int x, int a) {
return x + a;
}
}
As you can see, someMethod1 and mainLogic1 both have side effects which are hard to detect when looking at the code. On the other hand mainLogic2 doesn't have a side effect at all and someMethod2 side effect is easier to spot by just looking. This may seem like overkill, but it has made my Java code more readable, more testable and easier to refactor as it consists of large number of small methods with no side effects.