GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie kann eine gemeinsam genutzte Bibliothek (.so) eine Funktion aufrufen, die in ihrem Ladeprogramm implementiert ist?

Sie haben zwei Möglichkeiten, aus denen Sie wählen können:

Option 1:Exportieren Sie alle Symbole aus Ihrer ausführbaren Datei. Dies ist eine einfache Option, fügen Sie einfach beim Erstellen der ausführbaren Datei ein Flag -Wl,--export-dynamic hinzu . Dies würde alle Funktionen für Bibliotheksaufrufe verfügbar machen.

Option 2:Erstellen Sie eine Exportsymboldatei mit einer Liste von Funktionen und verwenden Sie -Wl,--dynamic-list=exported.txt . Dies erfordert einige Wartung, ist aber genauer.

Zur Demonstration:einfache ausführbare und dynamisch geladene Bibliothek.

#include <stdio.h>
#include <dlfcn.h>

void exported_callback() /*< Function we want to export */
{
    printf("Hello from callback!\n");
}

void unexported_callback() /*< Function we don't want to export */
{
    printf("Hello from unexported callback!\n");
}

typedef void (*lib_func)();

int call_library()
{
   void     *handle  = NULL;
   lib_func  func    = NULL;
   handle = dlopen("./libprog.so", RTLD_NOW | RTLD_GLOBAL);
   if (handle == NULL)
   {
       fprintf(stderr, "Unable to open lib: %s\n", dlerror());
       return -1;
   }
   func = dlsym(handle, "library_function");

   if (func == NULL) {
       fprintf(stderr, "Unable to get symbol\n");
      return -1;
   }

   func();
   return 0;
}

int main(int argc, const char *argv[])
{
    printf("Hello from main!\n");
    call_library();
    return 0;
}

Bibliothekscode (lib.c):

#include <stdio.h>
int exported_callback();

int library_function()
{
    printf("Hello from library!\n");
    exported_callback();
    /* unexported_callback(); */ /*< This one will not be exported in the second case */
    return 0;
}

Erstellen Sie also zuerst die Bibliothek (dieser Schritt unterscheidet sich nicht):

 gcc -shared -fPIC lib.c -o libprog.so

Erstellen Sie nun eine ausführbare Datei mit allen exportierten Symbolen:

 gcc -Wl,--export-dynamic main.c -o prog.exe -ldl

Beispiel ausführen:

 $ ./prog.exe
 Hello from main!
 Hello from library!
 Hello from callback!

Exportierte Symbole:

 $ objdump -e prog.exe -T | grep callback
 00000000004009f4 g    DF .text  0000000000000015  Base        exported_callback
 0000000000400a09 g    DF .text  0000000000000015  Base        unexported_callback

Jetzt mit der exportierten Liste (exported.txt ):

{
    extern "C"
    {
       exported_callback;
    };
};

Sichtbare Symbole erstellen und prüfen:

$ gcc -Wl,--dynamic-list=./exported.txt main.c -o prog.exe -ldl
$ objdump -e prog.exe -T | grep callback
0000000000400774 g    DF .text  0000000000000015  Base        exported_callback

Sie müssen eine Registerfunktion in Ihrer .so-Datei erstellen, damit die ausführbare Datei Ihrer .so-Datei einen Funktionszeiger für die spätere Verwendung geben kann.

So:

void in_main_func () {
// this is the function that need to be called from a .so
}

void (*register_function)(void(*)());
void *handle = dlopen("libmylib.so");

register_function = dlsym(handle, "register_function");

register_function(in_main_func);

die register_function muss den Funktionszeiger in einer Variablen in der .so-Datei speichern, wo ihn die andere Funktion in der .so-Datei finden kann.

Ihre mylib.c müsste etwa so aussehen:

void (*callback)() = NULL;

void register_function( void (*in_main_func)())
{
    callback = in_main_func();
}

void function_needing_callback() 
{
     callback();
}

  1. Platzieren Sie den Prototyp Ihrer Hauptfunktion in einer .h-Datei und fügen Sie ihn sowohl in Ihren Haupt- als auch in Ihren dynamischen Bibliothekscode ein.

  2. Mit GCC kompilieren Sie Ihr Hauptprogramm einfach mit dem -rdynamic Flagge.

  3. Nach dem Laden kann Ihre Bibliothek die Funktion vom Hauptprogramm aus aufrufen.

Eine kleine weitere Erklärung ist, dass Ihre dynamische Bibliothek nach dem Kompilieren ein undefiniertes Symbol für die Funktion enthält, die sich im Hauptcode befindet. Nachdem Ihre Haupt-App die Bibliothek geladen hat, wird das Symbol von der Symboltabelle des Hauptprogramms aufgelöst. Ich habe das obige Muster unzählige Male verwendet und es funktioniert wie ein Zauber.


Linux
  1. Linux – Wie kann sichergestellt werden, dass die Speicherseiten einer gemeinsam genutzten Bibliothek von mehreren Prozessen gemeinsam genutzt werden?

  2. Laden von Shared Libraries und RAM-Nutzung?

  3. Wie rufe ich eine Bash-Funktion in einem Bash-Skript in Awk auf?

  4. Einführung in gemeinsam genutzte Linux-Bibliotheken (So erstellen Sie gemeinsam genutzte Bibliotheken)

  5. So initialisieren Sie eine gemeinsam genutzte Bibliothek unter Linux

So erstellen und rufen Sie Funktionen in Bash auf

Aufrufen von C-Funktionen in C++, C++-Funktionen in C (C und C++ mischen)

Statischer Link der gemeinsam genutzten Bibliotheksfunktion in gcc

Wie kann ich bekommen, was meine Hauptfunktion zurückgegeben hat?

Wie kann die Eval-Funktion im Makefile verwendet werden?

So richten Sie googleTest als gemeinsam genutzte Bibliothek unter Linux ein