2011-09-24 795 views
10

我使用JNI在C++和Java之间传递数据。我需要通过一个“长”类型,我这样做使用类似:将C++ long类型转换为JNI jlong​​

long myLongVal = 100; 
jlong val = (jlong)myLongVal; 
CallStaticVoidMethod(myClass, "(J)V", (jvalue*)val); 

然而,在Java中,“长”参数检索时,它就会被检索到的一些非常大的负数。我究竟做错了什么?

+2

'long!= jlong​​'也许吧? – quasiverse

+0

奇怪的是,当我通过JNI传递一个值“1”时,Java不断收到4294967297。这个数字是费马号码。这似乎是一个非常巧合的价值。如果任何人有任何想法,为什么看到这个特殊的价值,我会有兴趣听到它。回到主题上,只要将'(jlong​​)值'强制转换为允许Java/JNI将其解析为正确的值1. – StockB

+1

4294967297 is(1 << 32)+ 1 – samgak

回答

12

当你传递一个jlong​​(这是64位)作为指针(很可能是32位)时,你必然会丢失数据。我不知道有什么约定,但尝试无论是这样的:

CallStaticVoidMethodA(myClass, "(J)V", (jvalue*)&val); //Note address-of! 

或本:

CallStaticVoidMethod(myClass, "(J)V", val); 

...A方法是采取jvalue阵列,无后缀的方法采取Ç等同于标Java类型。

第一段代码有点不安全;一个更好的,如果更详细的,替代方案是:

jvalue jv; 
jv.j = val; 
CallStaticVoidMethodA(myClass, "(J)V", &jv); 

在一些异国情调的CPU archtectures,为jlong变量和jvalue工会对齐要求可能会有所不同。当你明确声明一个联合时,编译器负责处理这个问题。

另请注意,C++ long数据类型通常是32位。 jlong​​是64位,在32位平台上,非标准C等价物是long long__int64

+3

“C++ long也是32位” - 在某些架构上,而不是在其他架构上。 x64 linux通常使用64位长。漫长的长时间无处不在(这是一个扩展IIRC)。 –

+1

的确如此。我会添加一个资格。 –

+0

感谢您的回答 - 不幸的是我已经尝试了两种建议的方法,并且在Java中检索时参数仍然显示为乱码,我还尝试使用int和float类型以及long :(奇怪的是下面的* does *工作, int类型(虽然没有意义) 'int someInt = 100; CallStaticVoidMethod(myClass,“(I)V”,(jvalue *)(jint)someInt);' –

3
CallStaticVoidMethod(myClass, "(J)V", (jvalue*)val); 

这是未定义的行为。您正在投射整数作为指针。它不是一个指针。您至少需要通过地址。这个代码会在大多数平台上立即崩溃。

+0

你是绝对正确的 - 我应该接受地址,但是这仍然不适用于我(不管浮动, int或long类型,因为我尝试了所有这些)。奇怪的是,下面的工作,只为int类型(尽管它没有任何意义)'int someInt = 100; CallStaticVoidMethod(myClass,“(I)V” ,(jvalue *)(jint)someInt) ;' –