传递指针从C到Java成为空指针、Java

2023-09-06 13:58:44 作者:野慌

我工作在x86 Android应用程序需要与C.我一直在使用痛饮/ JNI这样的伎俩已经整合了一些,事情已经平稳运行的大部分。然而,指针一直给我一些错误。

I'm working on an Android app for x86 that requires some integration with C. I've been using swig/JNI to do the trick, and things have been running smoothly for the most part. However, pointers have been giving me some errors.

我的问题是,我能够成功地引用变量的地址在仿真器(ARM),但装置(86)上,事情并没有去为好。

My issue is that I am able to successfully reference variable addresses in the emulator (ARM) but on a device (x86), things do not go as well.

使用例如,从的这个链接,我发现,在C中的任何分配变量的地址变成空一旦这个地址经过去渣。例如...

Using the example from this link, I discovered that the address of any allocated variable in C becomes NULL once this address passes over to Java. For example...

痛饮生成的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。

I have print statements checking the value of the address as it originates in C and passes over to Java. In new_intp(), the new variable is allocated a good looking address, but once this value returns to JNI and gets cast as a jlong, it turns to NULL.

在换句话说, *(INT **)及jresult =结果; 导致jresult为0。

In other words, *(int **)&jresult = result;causes jresult to be 0.

为什么会出现这种情况?有86的一些特殊性,不允许JNI的指针的工作吗?还是因为我是测试它一个物理设备上,而不是一个模拟器?

Why does this happen? Is there some particularity of x86 that disallows JNI to work with pointers? Or is it because I'm testing it on a physical device rather than an emulator?

问候

推荐答案

它看起来对我来说,它可能是一个字节序的问题。

It looks to me like it could be an endianness issue.

*(int **)&jresult = result; 

如果 INT 是32位,而 jresult 为64位,然后在大端架构,这可能得到意想不到的效果。

If int is 32 bits, and jresult is 64 bits, then on a big-endian architecture this could give unexpected results.

&放大器; jresult 是一个指向一个64位的值,所以如果你施放它指向一个32位的值,那么你就指着下部寻址两个组成32位字的。在大端系统中,这将是最显著字。因此,写一个32位字的64位值的最高显著结束后,你会得到一个64位的值,它比你所期望的更大的2 ^ 32次。

&jresult is a pointer to a 64-bit value, so if you cast it to a pointer to a 32-bit value, then you're pointing at the lower-addressed of the two constituent 32-bit words. In a big-endian system this will be the most significant word. So after writing a 32-bit word to the most significant end of the 64-bit value, you get a 64-bit value which is 2^32 times bigger than what you expect.

如果你的 LOGI 呼叫处理的参数为32位int,并含蓄下铸造从一个64位的值,那么它会给0。

If your LOGI call is treating the parameter as a 32-bit int, and implicitly down-casting it from a 64-bit value, then it will give 0.

您可以看到,如果这个工程呢?

Can you see if this works instead?

jresult = (jlong) result;