Jak załadowana funkcja biblioteczna wywoła symbol w głównej aplikacji?

Kiedy załadowana biblioteka współdzielona jest otwierana przez funkcję dlopen(), czy istnieje sposób na wywołanie funkcji w głównym programie?

Author: Jonathan Leffler, 2008-12-25

3 answers

Kod dlo.c (lib):

#include <stdio.h>

// function is defined in main program
void callb(void);

void test(void) {
    printf("here, in lib\n");
    callb();
}

Kompiluj z

gcc -shared -olibdlo.so dlo.c

Tutaj Kod głównego programu (skopiowany ze strony podręcznika dlopen i skorygowany):

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

Zbuduj z

gcc -ldl -rdynamic main.c

Wyjście:

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

Opcja -rdynamic umieszcza wszystkie symbole w dynamicznej tabeli symboli (która jest mapowana do pamięci), a nie tylko nazwy używanych symboli. Czytaj dalej tutaj . Oczywiście można również podać Wskaźniki funkcji (lub strukturę wskaźników funkcji), które zdefiniuj interfejs między biblioteką a głównym programem. To właściwie metoda, którą bym wybrał. Słyszałem od innych ludzi, że nie jest to takie łatwe do zrobienia -rdynamic w Windowsie, a także zapewniłoby czystszą komunikację między biblioteką a głównym programem( masz precyzyjną kontrolę nad tym, co można nazwać, a co nie), ale wymaga to również więcej utrzymania domu.

 18
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-26 15:26:16

Tak, Jeśli podasz swojej bibliotece wskaźnik do tej funkcji, jestem pewien, że biblioteka będzie w stanie uruchomić/wykonać funkcję w głównym programie.

Oto przykład, nie skompilowałem go więc uważaj ;)

/* 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);
}
 4
Author: hhafez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-25 11:21:16

Funkcja dlopen(), omówiona przez @ litb, jest przede wszystkim dostarczana w systemach wykorzystujących pliki obiektowe formatu ELF. Jest dość potężny i pozwala kontrolować, czy symbole odwołujące się do załadowanej biblioteki mogą być spełnione z głównego programu, i ogólnie pozwala im być spełnione. Nie wszystkie systemy ładowania bibliotek współdzielonych są tak elastyczne - należy pamiętać, jeśli chodzi o przenoszenie kodu.

Mechanizm wywołania zwrotnego opisany przez @hhafez działa teraz, gdy załamania w tym kodzie są wyprostowany.

 1
Author: Jonathan Leffler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-25 19:28:17