JAVA, JNI, DLL, C/C++ ... Esto no es basico:
Hola Socios, mi duda es:
Partimos de que tenemos una dll con funciones C para insertar y extraer estructuras en una zona compartida de memoria de la propia dll.
¿Como recuperar una estructura devuelta por la dll de C a traves de codigo JNI, en mi programa JAVA?
Espero vuesto bombardeo de respuestas ;-)
salu2 a to2
Partimos de que tenemos una dll con funciones C para insertar y extraer estructuras en una zona compartida de memoria de la propia dll.
¿Como recuperar una estructura devuelta por la dll de C a traves de codigo JNI, en mi programa JAVA?
Espero vuesto bombardeo de respuestas ;-)
salu2 a to2
No se puede de la manera que preguntas. Lo que necesitas hacer es hacer una clase como ProxyParaMisFunciones.java, y una clase equivalente a la estructura en C, digamos MiSuperEstructura. En esta clase haces metodos como
package mi.paquete;
public MiSuperEstructura native obtenMiEstructura();
No le pongas cuerpo a las funciones.
Dentro de tu declaracion de clase, escribe
static {
System.loadLibrary("miproxydllparajava.dll");
}
Asegurate de que el directorio donde vas a poner miproxydllparajava.dll se encuentre en el java.library.path
Ahora utiliza javah para generar un archivo C de cabecera. Va a generar algo asi como tu_paquete_MiSuperEstructura.h
Ahora tu necesitas escribir codigo en C/C++ "proxy" para ejecutar tus funciones C. En jdk1.3/include/jni.h puedes encontrar las macros para hacer interface con java desde C.
Para crear nuevos objetos desde C a traves de Java, necesitas hacer dos cosas. Primero, utilizar la macro "FindClass" asi:
(*env)->FindClass(env,"mi/paquete/MiSuperEstructura")
Despues, necesitas crear un nuevo objeto de esa clase con NewObject (tÃpicamente yo no lo hago, asi que no te puedo dar la función).
Como crear nuevos objetos desde C es un relajo y soy muy holgazán, prefiero utilizar mi clase en Java para crear los objetos desde un método y llamar este método desde C con todos los valores de la estructura.
He aqui una funcion que llama a System.out.println, que te dara una idea de como encontrar clases, llamar "getters" y ejecutar metodos:
/**
* Un System.out.println() para C
*/
void SYSTEMOUTPRINTLN(JNIEnv *env, char *str) {
jstring jstr = (*env)->NewStringUTF(env, str);
jclass System_class = (*env)->FindClass(env, "java/lang/System");
jfieldID fid_out = (*env)->GetStaticFieldID(env, System_class, "out","Ljava/io/PrintStream;");
jobject out = (*env)->GetStaticObjectField(env, System_class, fid_out);
jclass PrintStream_class = (*env)->FindClass(env,"java/io/PrintStream");
jmethodID mid_println = (*env)->GetMethodID(env,PrintStream_class,"println", "(Ljava/lang/String;)V");
if (mid_println == 0) {
printf("WOW! Couldn't find System.out.println! Message was %s", str);
return;
}
(*env)->CallVoidMethod(env, out, mid_println, jstr);
}
Tu codigo en C necesita cargar tu otro DLL, y ejecutar las funciones cuando tu otro codigo (en java) le diga que lo debe hacer. Normalmente procuro mantener tanto codigo en Java como sea posible, por aquello de la dificultad para encontrar bugs despues.
Espero que esto te ayude un poco.
Saludos!
package mi.paquete;
public MiSuperEstructura native obtenMiEstructura();
No le pongas cuerpo a las funciones.
Dentro de tu declaracion de clase, escribe
static {
System.loadLibrary("miproxydllparajava.dll");
}
Asegurate de que el directorio donde vas a poner miproxydllparajava.dll se encuentre en el java.library.path
Ahora utiliza javah para generar un archivo C de cabecera. Va a generar algo asi como tu_paquete_MiSuperEstructura.h
Ahora tu necesitas escribir codigo en C/C++ "proxy" para ejecutar tus funciones C. En jdk1.3/include/jni.h puedes encontrar las macros para hacer interface con java desde C.
Para crear nuevos objetos desde C a traves de Java, necesitas hacer dos cosas. Primero, utilizar la macro "FindClass" asi:
(*env)->FindClass(env,"mi/paquete/MiSuperEstructura")
Despues, necesitas crear un nuevo objeto de esa clase con NewObject (tÃpicamente yo no lo hago, asi que no te puedo dar la función).
Como crear nuevos objetos desde C es un relajo y soy muy holgazán, prefiero utilizar mi clase en Java para crear los objetos desde un método y llamar este método desde C con todos los valores de la estructura.
He aqui una funcion que llama a System.out.println, que te dara una idea de como encontrar clases, llamar "getters" y ejecutar metodos:
/**
* Un System.out.println() para C
*/
void SYSTEMOUTPRINTLN(JNIEnv *env, char *str) {
jstring jstr = (*env)->NewStringUTF(env, str);
jclass System_class = (*env)->FindClass(env, "java/lang/System");
jfieldID fid_out = (*env)->GetStaticFieldID(env, System_class, "out","Ljava/io/PrintStream;");
jobject out = (*env)->GetStaticObjectField(env, System_class, fid_out);
jclass PrintStream_class = (*env)->FindClass(env,"java/io/PrintStream");
jmethodID mid_println = (*env)->GetMethodID(env,PrintStream_class,"println", "(Ljava/lang/String;)V");
if (mid_println == 0) {
printf("WOW! Couldn't find System.out.println! Message was %s", str);
return;
}
(*env)->CallVoidMethod(env, out, mid_println, jstr);
}
Tu codigo en C necesita cargar tu otro DLL, y ejecutar las funciones cuando tu otro codigo (en java) le diga que lo debe hacer. Normalmente procuro mantener tanto codigo en Java como sea posible, por aquello de la dificultad para encontrar bugs despues.
Espero que esto te ayude un poco.
Saludos!