Casting a C++ long type to a JNI jlong
Solution 1
When you pass a jlong (which is 64 bit) as a pointer (which is, most likely, 32-bit) you necessarily lose data. I'm not sure what's the convention, but try either this:
CallStaticVoidMethodA(myClass, "(J)V", (jvalue*)&val); //Note address-of!
or this:
CallStaticVoidMethod(myClass, "(J)V", val);
It's ...A
methods that take a jvalue array, the no-postfix methods take C equivalents to scalar Java types.
The first snippet is somewhat unsafe; a better, if more verbose, alternative would be:
jvalue jv;
jv.j = val;
CallStaticVoidMethodA(myClass, "(J)V", &jv);
On some exotic CPU archtectures, the alignment requirements for jlong
variables and jvalue
unions might be different. When you declare a union explicitly, the compiler takes care of that.
Also note that C++ long
datatype is often 32-bit. jlong is 64 bits, on 32-bit platforms the nonstandard C equivalent is long long
or __int64
.
Solution 2
CallStaticVoidMethod(myClass, "(J)V", (jvalue*)val);
This is undefined behaviour. You are casting an integer to be a pointer. It is not a pointer. You need, at the very least, to pass the address. This code would on most platforms instantly crash.
lost_bits1110
Updated on June 04, 2022Comments
-
lost_bits1110 almost 2 years
I am using JNI to pass data between C++ and Java. I need to pass a 'long' type, and am doing so using something like:
long myLongVal = 100; jlong val = (jlong)myLongVal; CallStaticVoidMethod(myClass, "(J)V", (jvalue*)val);
However in Java, when the 'long' parameter is retrieved, it gets retrieved as some very large negative number. What am I doing wrong?
-
Drew Hall over 12 years"C++ long is 32-bit too"--true on some architectures, not on others. x64 linux usually uses 64-bit long. long long isn't available everywhere either (it's an extension IIRC).
-
Seva Alekseyev over 12 yearsTrue, that. I'll add a qualification.
-
lost_bits1110 over 12 yearsThanks for your answer - unfortunately I've tried both suggseted approaches and the parameter still appears garbled when retrieved in Java, I also tried with int and float types in addition to long :( Strangely the following does work, and only for int types (though it doesn't make sense)
int someInt = 100; CallStaticVoidMethod(myClass, "(I)V", (jvalue*)(jint)someInt );
-
lost_bits1110 over 12 yearsyou're absolutely right - I should be taking the address, however this still does not work for me (regardless of float, int or long type, as I tried all of these). Strangely, the following works, and only for int types (though it doesn't make any sense)
int someInt = 100; CallStaticVoidMethod(myClass, "(I)V", (jvalue*)(jint)someInt );
-
lost_bits1110 over 12 yearsDOH! It turns out I was not using
CallStaticVoidMethodA
, butCallStaticVoidMethod
. Appending the 'A' solves the problem. Thank-you!