我使用JNI在C++和Java之間傳遞數據。我需要通過一個「長」類型,我這樣做使用類似:將C++ long類型轉換爲JNI jlong
long myLongVal = 100;
jlong val = (jlong)myLongVal;
CallStaticVoidMethod(myClass, "(J)V", (jvalue*)val);
然而,在Java中,「長」參數檢索時,它就會被檢索到的一些非常大的負數。我究竟做錯了什麼?
我使用JNI在C++和Java之間傳遞數據。我需要通過一個「長」類型,我這樣做使用類似:將C++ long類型轉換爲JNI jlong
long myLongVal = 100;
jlong val = (jlong)myLongVal;
CallStaticVoidMethod(myClass, "(J)V", (jvalue*)val);
然而,在Java中,「長」參數檢索時,它就會被檢索到的一些非常大的負數。我究竟做錯了什麼?
當你傳遞一個jlong(這是64位)作爲指針(很可能是32位)時,你必然會丟失數據。我不知道有什麼約定,但嘗試無論是這樣的:
CallStaticVoidMethodA(myClass, "(J)V", (jvalue*)&val); //Note address-of!
或本:
CallStaticVoidMethod(myClass, "(J)V", val);
這...A
方法是採取jvalue陣列,無後綴的方法採取Ç等同於標Java類型。
第一段代碼有點不安全;一個更好的,如果更詳細的,替代方案是:
jvalue jv;
jv.j = val;
CallStaticVoidMethodA(myClass, "(J)V", &jv);
在一些異國情調的CPU archtectures,爲jlong
變量和jvalue
工會對齊要求可能會有所不同。當你明確聲明一個聯合時,編譯器負責處理這個問題。
另請注意,C++ long
數據類型通常是32位。 jlong是64位,在32位平臺上,非標準C等價物是long long
或__int64
。
「C++ long也是32位」 - 在某些架構上,而不是在其他架構上。 x64 linux通常使用64位長。漫長的長時間無處不在(這是一個擴展IIRC)。 –
的確如此。我會添加一個資格。 –
感謝您的回答 - 不幸的是我已經嘗試了兩種建議的方法,並且在Java中檢索時參數仍然顯示爲亂碼,我還嘗試使用int和float類型以及long :(奇怪的是下面的* does *工作, int類型(雖然沒有意義) 'int someInt = 100; CallStaticVoidMethod(myClass,「(I)V」,(jvalue *)(jint)someInt);' –
CallStaticVoidMethod(myClass, "(J)V", (jvalue*)val);
這是未定義的行爲。您正在投射整數作爲指針。它不是一個指針。您至少需要通過地址。這個代碼會在大多數平臺上立即崩潰。
你是絕對正確的 - 我應該接受地址,但是這仍然不適用於我(不管浮動, int或long類型,因爲我嘗試了所有這些)。奇怪的是,下面的工作,只爲int類型(儘管它沒有任何意義)'int someInt = 100; CallStaticVoidMethod(myClass,「(I)V」 ,(jvalue *)(jint)someInt) ;' –
'long!= jlong'也許吧? – quasiverse
奇怪的是,當我通過JNI傳遞一個值「1」時,Java不斷收到4294967297。這個數字是費馬號碼。這似乎是一個非常巧合的價值。如果任何人有任何想法,爲什麼看到這個特殊的價值,我會有興趣聽到它。回到主題上,只要將'(jlong)值'強制轉換爲允許Java/JNI將其解析爲正確的值1. – StockB
4294967297 is(1 << 32)+ 1 – samgak