I'm trying to pass a variable from c++ to java per reference via JNI. For the beginning I've tried it with some simple code:
Java
public static void inc(int val) {
System.out.println("inc called: " + val);
val++;
}
public static void dec(int val) {
System.out.println("dec called: " + val);
val--;
}
This should simply in-/decrement a variable created in c++ code with a Java method. The c++ part looks like this:
C++
jmethodID jDec = env->GetStaticMethodID(cls, "dec", "(I)V");
jmethodID jInc = env->GetStaticMethodID(cls, "inc", "(I)V");
jint val = 10;
printf("%d\n", val);
env->CallStaticVoidMethod(cls, jDec, &val);
printf("%d\n", val);
env->CallStaticVoidMethod(cls, jInc, val);
printf("%d\n", val);
As you see, I tried both, per reference and per value.
Output
10
dec called: -401031272
10
inc called: 10
10
Within the c++ code, the value is all the time 10, in Java it is either the address or the value.
Would be nice if you could give me a hint, thank you very much in advance.
As Wojtek said, Java passes arguments by value. You can add a return value your Java code:
public static int inc2(int val) {
System.out.println("inc called: " + val);
return val + 1;
}
and then call it from C++:
jmethodID inc2 = env->GetStaticMethodID(cls, "inc2", "(I)I");
jint result = env->CallStaticIntMethod(cls, inc2, val);
printf("inc2: %d\n", result);
Another approach is to use a wrapper class instead:
public class IntWrapper {
private int value;
public IntWrapper(int value) {
setInt(value);
}
public int getInt() {
return value;
}
public void setInt(int value) {
this.value = value;
}
}
and the following Java method:
public static void inc3(IntWrapper val) {
val.setInt(val.getInt()+1);
}
You can then call this from your C++ code:
// create wrapper object
jclass wrapper = env->FindClass("IntWrapper");
jmethodID constructor = env->GetMethodID(wrapper, "<init>", "(I)V");
jobject wrapperObject = env->NewObject(wrapper, constructor, val);
// print value before increment
jmethodID getInt = env->GetMethodID(wrapper, "getInt", "()I");
jint ret = env->CallIntMethod(wrapperObject, getInt);
printf("Wrapper value: %d\n", ret);
// call inc3
jmethodID inc3 = env->GetStaticMethodID(cls, "inc3", "(LIntWrapper;)V");
env->CallStaticVoidMethod(cls, inc3, wrapperObject);
// print result
ret = env->CallIntMethod(wrapperObject, getInt);
printf("Wrapper value after increment: %d\n", ret);
Alternatively you could use an int[] instead of the wrapper class as suggested by Wojtek.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With