Usando JNI en Java Eclipse (Linux), estoy cargando una biblioteca compartida dinámica llamada first.so . Hasta ahora todo va bien. El problema es que first.so también carga una biblioteca dinámica llamada second.so .
Cuando ejecuto el programa, recibo muchos errores de "símbolo indefinido" con respecto a los símbolos ubicados en second.so .
Parece que una biblioteca cargada con JNI no puede cargar otras bibliotecas C en tiempo de ejecución porque estamos en un entorno Java. ¿Es correcta mi suposición? ¿Necesito indicadores de compilación especiales para compilar la biblioteca first.so o son argumentos especiales para decirle a eclipse que intentará cargar un .so durante el tiempo de ejecución?
¡Gracias por adelantado!
Parece que una biblioteca cargada con JNI no puede cargar otras bibliotecas C en tiempo de ejecución porque estamos en un entorno Java. ¿Es correcta mi suposición?
No.
¿Cómo se usa libsecond.so por libfirst.so ? ¿Es una dependencia vinculada o está cargada por dlopen ?
He encontrado que algo como:
static { System.loadLibrary("second"); System.loadLibrary("first"); }en la clase que usa el JNI suele funcionar.
EDITAR: ahora que sé cómo está cargando libsecond.so que esto funcionó para mí:
prueba.java
public class Test { public static void main (String args[]) { test(); } private native static void test(); static { System.loadLibrary("first"); } } first.c -- La única unidad de traducción de libfirst.so
#include <jni.h> #include "Test.h" #include <dlfcn.h> #define LIBNAME "libsecond.so" #ifdef __cplusplus extern "C" { #endif /* * Class: Test * Method: test * Signature: ()V */ JNIEXPORT void JNICALL Java_Test_test(JNIEnv *env , jclass cls) { void* h; void (*sym)(void); h = dlopen(LIBNAME, RTLD_LAZY|RTLD_GLOBAL); if (h) { printf("dlopen " LIBNAME " worked\n"); sym = (void (*)(void))dlsym(h,"second"); sym(); } else { printf("dlopen " LIBNAME " failed\n"); } } #ifdef __cplusplus } #endif second.c -- La única unidad de traducción de libsecond.so
#include <stdio.h> void second(void) { printf("hello from second\n"); }Makefile
CFLAGS=-fPIC all : libfirst.so libsecond.so libsecond.so : second.o $(CC) -shared -Wl,-soname,libsecond.so.0 -o $@ $^ -lc libfirst.so : first.o $(CC) -shared -Wl,-soname,libfirst.so.0 -o $@ $^ -ldl -lc clean: rm -f *.o *.so Test.h puede ser producido por javah Test . Tenga en cuenta que libfirst.so y libsecond.so no están vinculados entre sí.
Todas las reglas habituales se aplican a dopen() desde una biblioteca cargada desde Java. En particular, verifique su LD_LIBRARY_PATH , rpath, runpath , etc. Consulte también dlopen falló: no se puede abrir el archivo de objeto compartido: no existe tal archivo o directorio