Seleccionar página

Llamando a Java desde C usando JNI

por | Feb 23, 2009 | Java

Seguro que el que más o el que menos ha escrito algo de código JNI para que java llame a una librería escrita en c, o incluso, quizás, que se vuelva a llamar desde c a java mediante un callback.

No obstante se presenta un problema cuando surge la siguiente idea: ¿y si guardo el objeto JNIEnv en un hilo o proceso de c, para posteriormente llamar a un objeto java a través del que se llamó originalmente a la función c que creó el hilo?

Inmediatamente pude confirmar que no, no se puede hacer. Al menos directamente. Para empezar, nuestra librería jni debe incluir lo siguiente:

static JavaVM * vm_handle;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved){

	vm_handle = vm;
	return JNI_VERSION_1_4;
}

Con esto ya tenemos acceso mediante un puntero estático al handle de la jvm. Lo siguiente que deberemos hacer es crear una referencia global al objeto java desde el que hemos llamado inicialmente a jni:

jni_obj = env->NewGlobalRef(obj);

Con eso ya podemos pasar el el puntero jni_obj a cualquier hilo.

Y ahora lo más importante: Asociar y obtener el handle del entorno jni al hilo en cuestión donde queramos usar jni.Ésta llamada debe hacerse dentro de la ejecución del hilo que va ha realizar la llamada.

JNIEnv * env;

vm_handle->AttachCurrentThread((void **)&env, NULL);

, donde vm_handle es el handle de la jvm que inicializamos mediante el uso de JNI_OnLoad.

Y ya está! Pasando los punteros adecuadamente, deberíamos ser capaces de hacer algo así:

jclass clazz = env->FindClass("NuestraClaseJava");
jmethodID mid = env->GetMethodID(clazz, "metodoCallback", "(Ljava/lang/String;)V");

jstring param = env->NewStringUTF("bla bla bla");

env->CallVoidMethod(obj, mid, param);

Por último recordar que hay que liberar al hilo del uso del env de jni:

vm_handler->DetachCurrentThread();

Y esto es todo! Por último remitiros a la documentación de Sun: Jni docs. Hasta la proxima!

Te puede interesar…

0 comentarios

Enviar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *