繁体   English   中英

将指针从 C 传递到 Java 变为 NULL

[英]Passing pointer from C to Java becomes NULL

我正在为 x86 开发 Android 应用程序,该应用程序需要与 C 进行一些集成。 我一直在使用 swig/JNI 来解决这个问题,并且大部分情况下都运行顺利。 但是,指针一直给我一些错误。

我的问题是我能够在模拟器(ARM)中成功引用变量地址,但在设备(x86)上,go 也没有。

使用此链接中的示例,我发现一旦该地址传递给 Java,C 中任何已分配变量的地址都会变为 NULL。 例如...

Swig 生成的 JNI:

SWIGEXPORT jlong JNICALL Java_exampleJNI_new_1intp(JNIEnv *jenv, jclass jcls) {
  jlong jresult = 0 ;
  int *result = 0 ;
  (void)jenv;
  (void)jcls;
  result = (int *)new_intp();
  LOGI("Result is %x", result);
  *(int **)&jresult = result; 
  LOGI("JResult is %x", jresult);
  return jresult;
}

包含 new_intp() 的源文件:

static int *new_intp() {
  return (int *) calloc(1,sizeof(int));
}

我有打印语句检查地址的值,因为它起源于 C 并传递给 Java。 在 new_intp() 中,新变量被分配了一个好看的地址,但是一旦这个值返回到 JNI 并被转换为 jlong,它就会变成 NULL。

换句话说, *(int **)&jresult = result; 导致 jresult 为 0。

为什么会这样? x86 是否有一些特殊性不允许 JNI 使用指针? 还是因为我在物理设备而不是模拟器上测试它?

问候

实际上,这是一个指针别名问题。 SWIG 使用的是老式的 C 指针技术,当优化开启时,这些技术在较新的 GCC 中不起作用。 埋在 SWIG 文档中,它专门说明了要做什么

重要的

如果您要使用通过 gcc(例如 -O2)打开的优化,请确保您还使用 -fno-strict-aliasing 进行编译。 从 gcc-4.0 开始,GCC 优化变得更加激进,并且会导致代码在打开严格的别名优化时失败。 有关详细信息,请参阅C/C++ 到 Java 类型映射部分。

在我看来,这可能是一个字节顺序问题。

*(int **)&jresult = result; 

如果int是 32 位,而jresult是 64 位,那么在大端架构上,这可能会产生意想不到的结果。

&jresult是一个指向 64 位值的指针,因此如果将其转换为指向 32 位值的指针,那么您将指向两个组成的 32 位字的低地址。 在大端系统中,这将是最重要的词。 因此,在将 32 位字写入 64 位值的最高有效端之后,您会得到一个 64 位值,它比您预期的值大 2^32 倍。

如果您的LOGI调用将参数视为 32 位 int,并从 64 位值隐式向下转换,则它将给出 0。

你能看看这是否有效吗?

jresult = (jlong) result; 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM