Comment une fonction de bibliothèque chargée appellerait un symbole dans l'application principale?

StackOverflow https://stackoverflow.com/questions/392416

  •  23-08-2019
  •  | 
  •  

Question

Lorsque chargé une bibliothèque partagée est ouverte par la fonction dlopen(), est-il un moyen pour elle d'appeler les fonctions dans le programme principal?

Était-ce utile?

La solution

Code 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();
}

Compiler avec

gcc -shared -olibdlo.so dlo.c

Voici le code du programme principal (copié à partir manpage dlopen et ajusté):

#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);
}

Construire avec

gcc -ldl -rdynamic main.c

Sortie:

[js@HOST2 dlopen]$ LD_LIBRARY_PATH=. ./a.out
here, in lib
here, i'm back
[js@HOST2 dlopen]$

L'option -rdynamic met tous les symboles dans la table des symboles (dynamique qui est mis en correspondance en mémoire), non seulement les noms des symboles utilisés. En savoir plus à ce sujet . Bien sûr, vous pouvez également fournir des pointeurs de fonction (ou un struct de pointeurs de fonction) qui définissent l'interface entre la bibliothèque et votre programme principal. Il est en fait la méthode que je choisirais probablement. J'ai entendu d'autres personnes que ce n'est pas si facile à faire -rdynamic dans les fenêtres, et ce serait également une communication plus propre entre la bibliothèque et le programme principal (vous avez un contrôle précis sur ce qui peut être appelé et non), mais il faut aussi plus de maison tenue.

Autres conseils

Oui, si vous fournissez votre bibliothèque un pointeur vers cette fonction, je suis sûr que la bibliothèque sera en mesure d'exécuter / exécuter la fonction dans le programme principal.

Voici un exemple, n'a pas compilé alors méfiez-vous;)

/* 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);
}

La fonction dlopen(), tel que discuté par @litb, est principalement fourni sur les systèmes utilisant des fichiers objets format ELF. Il est assez puissant et vous permettra de contrôler si les symboles référencés par la bibliothèque chargée peut être satisfait du programme principal, et ne généralement qu'ils soient satisfaits. Tous les systèmes de chargement de bibliothèques partagées sont aussi souples - il faut savoir s'il s'agit de portage de votre code

.

Le mécanisme de rappel décrit par @hhafez fonctionne maintenant que les petits défauts dans ce code sont redressés.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top