【问题标题】:Passing pointer from C to Java becomes NULL将指针从 C 传递到 Java 变为 NULL
【发布时间】:2011-07-19 19:52:19
【问题描述】:

我正在开发一个适用于 x86 的 Android 应用程序,该应用程序需要与 C 进行一些集成。我一直在使用 swig/JNI 来实现这一目标,并且大部分情况下运行顺利。但是,指针一直给我一些错误。

我的问题是我能够在模拟器 (ARM) 中成功引用变量地址,但在设备 (x86) 上,事情就不那么顺利了。

使用this link 中的示例,我发现一旦该地址传递给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 使用指针?还是因为我是在物理设备而不是模拟器上测试它?

问候

【问题讨论】:

  • 哎呀,非得叫它this吗?我相信这是 Java 和 C++ 中的保留关键字。
  • 在 C 中,它不是。不过,给任何变量起这个名字可能不是最好的习惯。将对其进行编辑。
  • 哦,对不起,我被你的问题标题弄糊涂了。这是一个 C 或 C++ 问题,我们可以适当地标记它吗?
  • 你知道jlong​​是64位类型吗?
  • 是的,我想我知道地址返回给 Java 是 64 位长。

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


【解决方案1】:

实际上,这是一个pointer-aliasing 问题。 SWIG 使用的是老式的 C 指针技术,当优化开启时,这些技术在较新的 GCC 中不起作用。埋在 SWIG 文档中,特别是 says what to do

重要

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

【讨论】:

    【解决方案2】:

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

    *(int **)&jresult = result; 
    

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

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

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

    你能看看这是否可行吗?

    jresult = (jlong) result; 
    

    【讨论】:

    • @digitalmouse12 也许系统的某些部分不知道它应该是小端 - 请记住 x86 android 不是官方的。尝试逐字节从内存中转储 jresult 的原始值(指针,而不是其目标),看看直接赋值情况和指针黑客情况之间是否存在差异。当我在 32 位桌面 linux 上执行此操作时,我没有得到任何区别,但这不是您的目标系统。
    • @Graham Borland:实际上这是一个pointer-aliasing 问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-20
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多