2011-09-24 10 views
10

Używam JNI do przekazywania danych między C++ i Javą. Muszę zdać „długi” rodzaj, a więc przy użyciu robię coś takiego:Przesyłanie długiego typu C++ do JNI jlong ​​

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

Jednak w Javie, gdy parametr „długi” zostanie pobrana, zostaje pobrane jako pewnego bardzo dużą liczbą ujemną. Co ja robię źle?

+2

'długo! = Jlong' może? – quasiverse

+0

Co ciekawe, Java otrzymywała 4294967297, gdy przekazałem mu wartość "1" przez JNI. Ta liczba to numer Fermata. Wydaje się to niezwykle przypadkową wartością. Jeśli ktoś ma jakieś pomysły, dlaczego ta konkretna wartość była widoczna, byłbym zainteresowany słuchaniem tego. Wracając do tematu, przesłanie mojego long jako '(jlong) value 'pozwoliło Java/JNI przeanalizować go do poprawnej wartości 1. – StockB

+1

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

Odpowiedz

12

Po przekazaniu znacznika jlong ​​(który jest 64-bitowy) jako wskaźnika (który najprawdopodobniej jest 32-bitowy), konieczne jest utracenie danych. Nie jestem pewien, co to jest konwencja, ale spróbuj albo to:

CallStaticVoidMethodA(myClass, "(J)V", (jvalue*)&val); //Note address-of! 

lub to:

CallStaticVoidMethod(myClass, "(J)V", val); 

To ...A metod, które zajmują się jvalue tablicę, metody bez przyrostkowe wziąć odpowiedniki C do skalara Typy Java.

Pierwszy fragment jest nieco niebezpieczny; lepiej, gdyby bardziej gadatliwy, alternatywą byłoby:

jvalue jv; 
jv.j = val; 
CallStaticVoidMethodA(myClass, "(J)V", &jv); 

Na niektórych egzotycznych archtectures CPU, wymagania wyrównania dla jlong zmiennych i jvalue związków mogą być różne. Kiedy jawnie deklarujesz związek, kompilator się tym zajmuje. Uwaga: Typ danych C++ long C++ jest często 32-bitowy. jlong ​​ma 64 bity, na 32-bitowych platformach niestandardowy odpowiednik C to long long lub __int64.

+3

" C++ long is 32-bit too "- -true na niektórych architekturach, a nie na innych. Linux x64 zwykle używa 64-bitowej długości. długo nie jest dostępne wszędzie (jest to rozszerzenie IIRC). –

+1

To prawda. Dodam kwalifikację. –

+0

Dziękuję za odpowiedź - niestety próbowałem obu sugerowanych podejść, a parametr nadal wydaje się zniekształcony po pobraniu w Javie, próbowałem również z typami int i float oprócz długich :(Dziwnie następujące * działa * i tylko dla typy int (choć to nie ma sensu) 'int someInt = 100; CallStaticVoidMethod (myClass," (I) V "(jvalue *) (jint) someInt);' –

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

To jest niezdefiniowane zachowanie. Przeznaczasz liczbę całkowitą jako wskaźnik. To nie jest wskaźnik. Musisz przynajmniej podać adres adres. Ten kod na większości platform natychmiast się zawiesił.

+0

masz absolutną rację - powinienem przyjmować adres, jednak to nadal nie działa dla mnie (bez względu na float, int lub długi typ, tak jak ja próbowałem wszystkich tych.) Dziwnie, następujące prace, i tylko dla typów int (choć to nie ma żadnego sensu) 'int someInt = 100; CallStaticVoidMethod (myClass," (I) V " , (jvalue *) (jint) someInt) ; ' –

Powiązane problemy