2011-10-02 19 views
15

Estoy construyendo una aplicación Java que usa una biblioteca compartida escrita en C++ y compilada para diferentes sistemas operativos. El problema es que esta biblioteca compartida en sí misma depende de una biblioteca adicional que normalmente encuentra en la variable de entorno adecuada (RUTA, VÍA LIBRERA o VÍA LISTA LD).Cargar biblioteca compartida por ruta en tiempo de ejecución

Puedo, pero no quiero, configurar estas variables de entorno. Prefiero cargar las bibliotecas compartidas necesarias desde una ruta dada en tiempo de ejecución, como un complemento. Y no, no quiero ninguna aplicación de inicio que comience un nuevo proceso con un nuevo entorno. ¿Alguien sabe cómo lograr esto?

Sé que esto debe ser posible, ya que una de las bibliotecas que uso es capaz de cargar sus complementos desde una ruta determinada. Por supuesto, prefiero el código independiente de la plataforma, pero si esto no es posible, las soluciones separadas para Windows, Linux y MacOS también lo harían.

EDITAR debería haber mencionado que la biblioteca compartida Me gustaría utilizar es orientado a objetos, lo que significa que una unión de funciones individuales no lo hará.

+0

¿Cómo carga la biblioteca de Java? –

+0

Java Native Access (JNA) – aRestless

Respuesta

8

En Windows, puede usar LoadLibrary, y en Linux, dlopen. Las API son extremadamente similares y pueden cargar un archivo so/dll directamente al proporcionar la ruta completa. Eso funciona si se trata de una dependencia de tiempo de ejecución (después de la carga, que "enlace" llamando GetProcAddress/dlsym.)

15

sistemas Un UNIX/Linux puede utilizar dlopen. La cuestión entonces es que hay que ir a buscar todos los símbolos que necesita a través de dlsym

ejemplo simple:

typedef int (*some_func)(char *param); 

void *myso = dlopen("/path/to/my.so", RTLD_NOW); 
some_func *func = dlsym(myso, "function_name_to_fetch"); 
func("foo"); 
dlclose(myso); 

cargará el .so y ejecutar function_name_to_fetch() desde allí. Consulte la página man dlopen (1) para obtener más información.

+0

Creo que debería haber agregado que la biblioteca compartida está orientada a objetos. Si solo las funciones pueden "vincularse", esto no funcionará, ¿verdad? – aRestless

+0

Si conoce el nombre que genera el enlazador, puede acceder a cualquier símbolo. Una buena práctica es tener una función que utiliza convenciones de llamadas C que devuelve un puntero a una estructura que contiene objetos o algo. – johannes

+0

Bueno, ya lo hago - para acceder a la biblioteca a través de Java. La biblioteca de C++ que estoy escribiendo no es más que un apéndice que usa la biblioteca de terceros (que no puedo modificar). – aRestless

1

No creo que puedas hacerlo por eso.

La mayoría de los Dlls tienen algún tipo de función init() que se debe invocar después de haber sido cargada, y alguna vez esa función init() necesita algunos parámetros y devuelve algún handle para llamar a las funciones del dll. ¿Conoces la definición de la biblioteca adicional?

Entonces, la primera biblioteca no puede simplemente mirar si el DLL X está en RAM solamente usando su nombre. El que necesita puede estar en un directorio diferente o en una compilación/versión diferente. El sistema operativo reconocerá la biblioteca si la ruta completa es la misma que otra ya cargada y la compartirá en lugar de cargarla por segunda vez.

La otra biblioteca puede cargar sus complementos desde otra ruta porque está escrito para no depender de PATH y son sus propios complementos.

¿Ha intentado actualizar las variables de entorno del proceso desde el código antes de cargar el Dll? Eso no dependerá de un proceso inicial.

3

Estoy de acuerdo con los otros carteles sobre el uso de dlopen y LoadLibrary. El libltdl le brinda una interfaz independiente de la plataforma para estas funciones.

Cuestiones relacionadas