【问题标题】:Casting a C++ long type to a JNI jlong将 C++ long 类型转换为 JNI jlong
【发布时间】:2011-11-24 02:04:07
【问题描述】:

我正在使用 JNI 在 C++ 和 Java 之间传递数据。我需要传递一个“长”类型,并且正在使用类似的东西:

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

然而,在 Java 中,当检索 'long' 参数时,它会被检索为一个非常大的负数。我究竟做错了什么?

【问题讨论】:

  • 奇怪的是,当我通过 JNI 将值“1”传递给 Java 时,它一直得到 4294967297。这个数就是费马数。这似乎是一个非常巧合的值。如果有人对为什么看到这个特定值有任何想法,我很想听听。回到主题,将我的 long as (jlong) value 转换为允许 Java/JNI 将其解析为正确的值 1。
  • 4294967297 是 (1

标签: java android c++ java-native-interface android-ndk


【解决方案1】:

当您将 jlong​​(64 位)作为指针(很可能是 32 位)传递时,您必然会丢失数据。我不确定约定是什么,但试试这个:

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

或者这个:

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

...A 方法采用 jvalue 数组,无后缀方法采用 C 等价于标量 Java 类型。

第一个 sn-p 有点不安全;一个更好的替代方案是:

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

在一些奇特的 CPU 架构上,jlong 变量和 jvalue 联合的对齐要求可能不同。当你显式声明一个联合时,编译器会处理这个问题。

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

【讨论】:

  • “C++ long 也是 32 位的”——在某些架构上是正确的,而在其他架构上则不然。 x64 linux 通常使用 64 位长。 long long 也不是随处可用(它是 IIRC 的扩展)。
  • 确实如此。我将添加一个资格。
  • 感谢您的回答 - 不幸的是,我已经尝试了两种建议的方法,并且在 Java 中检索参数时仍然出现乱码,我还尝试了 int 和 float 类型以及 long :( 奇怪的是以下 确实 工作,并且仅适用于 int 类型(尽管它没有意义)int someInt = 100; CallStaticVoidMethod(myClass, "(I)V", (jvalue*)(jint)someInt );
  • 卫生署!原来我用的不是CallStaticVoidMethodA,而是CallStaticVoidMethod。附加“A”可以解决问题。谢谢!
【解决方案2】:
CallStaticVoidMethod(myClass, "(J)V", (jvalue*)val);

这是未定义的行为。您正在将整数转换为指针。它不是指针。您至少需要传递地址。此代码在大多数平台上会立即崩溃。

【讨论】:

  • 你是绝对正确的 - 我应该获取地址,但这仍然对我不起作用(无论是浮点数、整数还是长整数,因为我尝试了所有这些)。奇怪的是,以下工作,仅适用于 int 类型(虽然它没有任何意义)int someInt = 100; CallStaticVoidMethod(myClass, "(I)V", (jvalue*)(jint)someInt );
猜你喜欢
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-21
  • 2020-04-08
  • 1970-01-01
相关资源
最近更新 更多