2011-09-24 25 views
10

Estoy utilizando JNI para pasar datos entre C++ y Java. Necesito pasar un tipo 'larga', y estoy haciendo así que usar algo como:Transmitir un tipo largo de C++ a un jlong ​​JNI

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

Sin embargo, en Java, cuando se recupera el parámetro 'larga', se pone recuperados como algunos gran número negativo. ¿Qué estoy haciendo mal?

+2

'long! = Jlong' ¿quizás? – quasiverse

+0

Curiosamente, Java siguió obteniendo 4294967297 cuando pasé un valor de "1" a través de JNI. Ese número es un número de Fermat. Parece un valor tremendamente casual. Si alguien tiene alguna idea sobre por qué se vio este valor en particular, estaría interesado en escucharlo. Volviendo al tema, el lanzamiento de mi valor largo como '(jlong) value permitió que Java/JNI lo analizara con el valor correcto de 1. – StockB

+1

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

Respuesta

12

Cuando pasa un jlong ​​(que es de 64 bits) como un puntero (que es, muy probablemente, de 32 bits), necesariamente pierde datos. No estoy seguro de cuál es la convención, pero trato, ya sea esto:

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

o esto:

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

¡Es ...A métodos que toman una matriz jvalue, los métodos no-postfijos la C equivalentes a escalar Tipos de Java.

El primer fragmento es algo inseguro; una mejor, si más detallado, alternativa sería:

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

En algunos archtectures CPU exóticos, los requisitos de alineación para jlong variables y jvalue sindicatos podrían ser diferentes. Cuando declaras una unión explícitamente, el compilador se encarga de eso.

También tenga en cuenta que C++ long datatype es a menudo de 32 bits. jlong ​​es de 64 bits, en plataformas de 32 bits, el equivalente en C no estándar es long long o __int64.

+3

" C++ long también es de 32 bits "- -Es cierto en algunas arquitecturas, no en otras. x64 linux generalmente usa 64 bits de largo. long long no está disponible en todas partes tampoco (es una extensión IIRC). –

+1

Es cierto, eso. Agregaré una calificación. –

+0

Gracias por su respuesta - desafortunadamente probé los dos enfoques sugeridos y el parámetro aún parece distorsionado cuando se lo recupero en Java, también intenté con los tipos int y float además de long :(Extrañamente el siguiente * does * funciona, y solo para tipos int (aunque no tiene sentido) 'int someInt = 100; CallStaticVoidMethod (myClass," (I) V ", (jvalue *) (jint) someInt);' –

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

Comportamiento indefinido. Estás emitiendo un número entero para ser un puntero. No es un puntero. Necesita, al menos, pasar la dirección . Este código se bloquearía instantáneamente en la mayoría de las plataformas.

+0

tienes toda la razón, debería tomar la dirección, sin embargo, esto todavía no funciona para mí (independientemente de la flotación, int o long type, como probé con todos estos). Extrañamente, funciona lo siguiente, y solo para tipos int (aunque no tiene ningún sentido) 'int someInt = 100; CallStaticVoidMethod (myClass," (I) V " , (jvalue *) (jint) someInt) ; ' –

Cuestiones relacionadas