簡體   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