Cuando se carga una biblioteca compartida se abre a través de la función dlopen()
, ¿hay alguna forma de llamar funciones en el programa principal?¿Cómo llamaría una función de biblioteca cargada a un símbolo en la aplicación principal?
Respuesta
Código de dlo.c (lib):
#include <stdio.h>
// function is defined in main program
void callb(void);
void test(void) {
printf("here, in lib\n");
callb();
}
compilar con
gcc -shared -olibdlo.so dlo.c
Aquí el código del programa principal (copiado de la página de manual de dlopen, y ajustado):
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void callb(void) {
printf("here, i'm back\n");
}
int
main(int argc, char **argv)
{
void *handle;
void (*test)(void);
char *error;
handle = dlopen("libdlo.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
dlerror(); /* Clear any existing error */
*(void **) (&test) = dlsym(handle, "test");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(EXIT_FAILURE);
}
(*test)();
dlclose(handle);
exit(EXIT_SUCCESS);
}
Construir con
gcc -ldl -rdynamic main.c
Salida:
[[email protected] dlopen]$ LD_LIBRARY_PATH=. ./a.out
here, in lib
here, i'm back
[[email protected] dlopen]$
La opción -rdynamic
pone todos los símbolos en la tabla dinámica símbolo (que está asignada en la memoria), no sólo los nombres de los símbolos utilizados . Lea más al respecto here. Por supuesto, también puede proporcionar punteros a funciones (o una estructura de indicadores de función) que definan la interfaz entre la biblioteca y su programa principal. En realidad, es el método que elegiría probablemente. Escuché de otras personas que no es tan fácil hacer -rdynamic
en Windows, y también haría una comunicación más clara entre la biblioteca y el programa principal (tienes un control preciso de lo que se puede llamar y no), pero también requiere más mantenimiento de la casa.
Impresionante responder. Alguien ha ganado 10k rep :-) –
Esa es una forma interesante de hacer el casting. ¿No es más normal convertir el valor de retorno de dlsym() al puntero para funcionar, en lugar de pretender que el puntero al que está asignando es del mismo tipo que la función que devuelve dlsym()? –
C no dice qué sucede si lanza desde un vacío * a un puntero de función. lamentablemente no encontré el párrafo que establezca que es un comportamiento indefinido, pero la página de manual dice que así lo dice. –
Sí, si proporciona a su biblioteca un puntero a esa función, estoy seguro de que la biblioteca podrá ejecutar/ejecutar la función en el programa principal.
Aquí es un ejemplo, no han compilado así que ten cuidado;)
/* in main app */
/* define your function */
int do_it(char arg1, char arg2);
int do_it(char arg1, char arg2){
/* do it! */
return 1;
}
/* some where else in main app (init maybe?) provide the pointer */
LIB_set_do_it(&do_it);
/** END MAIN CODE ***/
/* in LIBRARY */
int (*LIB_do_it_ptr)(char, char) = NULL;
void LIB_set_do_it(int (*do_it_ptr)(char, char)){
LIB_do_it_ptr = do_it_ptr;
}
int LIB_do_it(){
char arg1, arg2;
/* do something to the args
...
... */
return LIB_do_it_ptr(arg1, arg2);
}
do_it_ptr toma un puntero a una función que espera 3 argumentos char; usted asigna punteros a función para funciones que solo toman 2 argumentos char. La declaración externa para doit() apenas se necesita. Do_it_ptr no es necesario; simplemente puede pasar do_it por su nombre donde actualmente pasa do_it_ptr. Etc! –
eso es correcto :) de hecho, también podría deshacerse de LIB_get_it() y simplemente definir un nuevo LIB_do_it (int (* do_it_ptr) (char, char, char)) {return do_it_ptr (arg1, arg2, arg3)} – hhafez
La función dlopen()
, como se describe en @litb, se proporciona principalmente en sistemas que utilizan archivos de objetos de formato ELF. Es bastante potente y le permitirá controlar si los símbolos a los que hace referencia la biblioteca cargada se pueden satisfacer desde el programa principal y, en general, permite que se satisfagan. No todos los sistemas de carga de bibliotecas compartidas son tan flexibles, tenga en cuenta si se trata de portar su código.
El mecanismo de devolución de llamada descrito por @hhafez funciona ahora que las fallas en ese código están enderezadas.
enderezó los dobleces;) gracias – hhafez
- 1. Símbolo no definido "typeinfo" con la biblioteca cargada dinámicamente
- 2. Biblioteca estática cargada dos veces
- 3. Biblioteca no cargada
- 4. Rango de direcciones de una biblioteca cargada dinámicamente en Windows
- 5. Cómo crear una biblioteca C# que está cargada en la memoria una sola vez?
- 6. ¿Cómo aplico un símbolo como una función en Scheme?
- 7. Qué función en glibc llama a la función principal
- 8. dyld: Biblioteca no cargada: cuando la aplicación se ejecuta desde la línea de comando
- 9. Cómo forzar a los símbolos de una biblioteca estática a ser incluidos en una compilación de biblioteca compartida?
- 10. CMake nombre de salida para la biblioteca cargada dinámicamente?
- 11. ¿Cómo cerrar la aplicación antes de que esté completamente cargada?
- 12. Biblioteca nativa sqljdbc_auth.dll ya cargada en otro cargador de clase
- 13. ¿Hay una función llamada en cualquier momento CUALQUIER página cargada en su aplicación?
- 14. ¿Verifica si ya está cargada una biblioteca dll? (Java)
- 15. Sigabrt en la función principal
- 16. Cómo llamar a una función en un iframe desde la página principal?
- 17. ¿Common Lisp equivalente a la función principal de Haskell? función
- 18. ¿Cómo llamar a una función desde una biblioteca compartida?
- 19. Python cómo salir de la función principal
- 20. ADVERTENCIA snappy.LoadSnappy: Snappy biblioteca nativa no cargada
- 21. ¿Cómo se llamaría este patrón enum?
- 22. cómo llamar a la función en ejecutable desde mi biblioteca?
- 23. ¿Cómo uso una función de biblioteca Haskell?
- 24. Cómo declarar un contexto de aplicación principal
- 25. Acceda a la clase de proyecto principal desde una clase de biblioteca
- 26. ImportError: [nombre de la biblioteca] .so: undefined símbolo: [nombre de la función]
- 27. Cómo pasar la imagen cargada a template.html en Flask
- 28. "dyld: Biblioteca no cargada", "libruby.1.9.1.dylib" al llamar a "mvim". en la línea de comando
- 29. Llamando a la función de biblioteca C/C++ desde PHP
- 30. Cómo llamar a una función de biblioteca desde un menú desplegable de hoja de cálculo generado por la misma biblioteca
Las respuestas a continuación hacen un buen trabajo respondiendo la pregunta, pero tengo que preguntar: ¿podría explicar el contexto más amplio de este requisito? Cuando he encontrado la necesidad de hacer esto, es para construir un modelo de extensión/complemento o porque mi programa no está muy bien factorizado. – reuben
también podría usarse para control de inversión, ¿no? Defina el flujo de la aplicación en la biblioteca mientras la implementación real está en la aplicación principal – hhafez
Piense en un módulo Perl XS. Necesita usar funciones de Perl de bajo nivel (digamos newSViv() para crear un SV a partir de un entero); es conveniente si el módulo usa la nueva función de Vivo() de Perl, en lugar de incrustar su propia copia en el objeto compartido del módulo. Además, el código necesita la biblioteca C estándar. –