2011-09-24 169 views
10

我使用JNI在C++和Java之間傳遞數據。我需要通過一個「長」類型,我這樣做使用類似:將C++ long類型轉換爲JNI jlong​​

long myLongVal = 100; 
jlong val = (jlong)myLongVal; 
CallStaticVoidMethod(myClass, "(J)V", (jvalue*)val); 

然而,在Java中,「長」參數檢索時,它就會被檢索到的一些非常大的負數。我究竟做錯了什麼?

+2

'long!= jlong​​'也許吧? – quasiverse

+0

奇怪的是,當我通過JNI傳遞一個值「1」時,Java不斷收到4294967297。這個數字是費馬號碼。這似乎是一個非常巧合的價值。如果任何人有任何想法,爲什麼看到這個特殊的價值,我會有興趣聽到它。回到主題上,只要將'(jlong​​)值'強制轉換爲允許Java/JNI將其解析爲正確的值1. – StockB

+1

4294967297 is(1 << 32)+ 1 – samgak

回答

12

當你傳遞一個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

+3

「C++ long也是32位」 - 在某些架構上,而不是在其他架構上。 x64 linux通常使用64位長。漫長的長時間無處不在(這是一個擴展IIRC)。 –

+1

的確如此。我會添加一個資格。 –

+0

感謝您的回答 - 不幸的是我已經嘗試了兩種建議的方法,並且在Java中檢索時參數仍然顯示爲亂碼,我還嘗試使用int和float類型以及long :(奇怪的是下面的* does *工作, int類型(雖然沒有意義) 'int someInt = 100; CallStaticVoidMethod(myClass,「(I)V」,(jvalue *)(jint)someInt);' –

3
CallStaticVoidMethod(myClass, "(J)V", (jvalue*)val); 

這是未定義的行爲。您正在投射整數作爲指針。它不是一個指針。您至少需要通過地址。這個代碼會在大多數平臺上立即崩潰。

+0

你是絕對正確的 - 我應該接受地址,但是這仍然不適用於我(不管浮動, int或long類型,因爲我嘗試了所有這些)。奇怪的是,下面的工作,只爲int類型(儘管它沒有任何意義)'int someInt = 100; CallStaticVoidMethod(myClass,「(I)V」 ,(jvalue *)(jint)someInt) ;' –