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

So verzögern Sie das Laden einer gemeinsam genutzten Bibliothek unter Linux

Das verzögerte Laden ist KEINE Laufzeitfunktion. MSVC++ hat es ohne Hilfe von Windows implementiert. Und wie dlopen ist die einzige Möglichkeit unter Linux, GetProcAddress ist die einzige Laufzeitmethode unter Windows.

Also, was ist dann verzögertes Laden? Es ist ganz einfach:Jeder Aufruf einer DLL muss über einen Zeiger gehen (da Sie nicht wissen, wo sie geladen wird). Dies wurde immer vom Compiler und Linker für Sie erledigt. Aber beim verzögerten Laden setzt MSVC++ diesen Zeiger zunächst auf einen Stub, der LoadLibrary aufruft und GetProcAddress für dich.

Clang kann dasselbe ohne Hilfe von ld tun . Zur Laufzeit ist es nur ein gewöhnlicher dlopen aufrufen, und Linux kann nicht feststellen, dass Clang es eingefügt hat.


Um die Antwort von MSalter zu ergänzen, kann man den Windows-Ansatz zum verzögerten Laden unter Linux leicht nachahmen, indem man eine kleine statische Stub-Bibliothek erstellt, die versuchen würde, dlopen auszuführen Benötigte Bibliothek beim ersten Aufruf einer ihrer Funktionen (Ausgeben einer Diagnosemeldung und Beenden, wenn dlopen fehlgeschlagen ist) und Weiterleiten aller Aufrufe an sie.

Solche Stub-Bibliotheken können von Hand geschrieben, durch ein projekt-/bibliotheksspezifisches Skript oder durch das universelle Tool Implib.so generiert werden:

$ implib-gen.py libxyz.so
$ gcc myapp.c libxyz.tramp.S libxyz.init.c ...

Diese Funktionalität kann auf portable Weise mit dem Proxy-Entwurfsmuster erreicht werden.

Im Code kann es etwa so aussehen:

#include <memory>

// SharedLibraryProxy.h
struct SharedLibraryProxy
{
    virtual ~SharedLibraryProxy() = 0;

    // Shared library interface begin.
    virtual void foo() = 0;
    virtual void bar() = 0;
    // Shared library interface end.

    static std::unique_ptr<SharedLibraryProxy> create();
};

// SharedLibraryProxy.cc
struct SharedLibraryProxyImp : SharedLibraryProxy
{
    void* shared_lib_ = nullptr;
    void (*foo_)() = nullptr;
    void (*bar_)() = nullptr;

    SharedLibraryProxyImp& load() {
        // Platform-specific bit to load the shared library at run-time.
        if(!shared_lib_) { 
            // shared_lib_ = dlopen(...);
            // foo_ = dlsym(...)
            // bar_ = dlsym(...)
        }
        return *this;
    }

    void foo() override {
        return this->load().foo_();
    }

    void bar() override {
        return this->load().bar_();
    }
};

SharedLibraryProxy::~SharedLibraryProxy() {}

std::unique_ptr<SharedLibraryProxy> SharedLibraryProxy::create() {
    return std::unique_ptr<SharedLibraryProxy>{new SharedLibraryProxyImp};
}

// main.cc
int main() {
    auto shared_lib = SharedLibraryProxy::create();
    shared_lib->foo();
    shared_lib->bar();
}

Linux
  1. Wie man einen alten Computer wieder brauchbar macht

  2. Wie kann man ein freigegebenes Verzeichnis per Sftp zugänglich machen?

  3. So initialisieren Sie eine gemeinsam genutzte Bibliothek unter Linux

  4. Wie kann ich die Liste der Funktionen anzeigen, die eine gemeinsam genutzte Linux-Bibliothek exportiert?

  5. Wie wird die Versionierung einer gemeinsam genutzten Bibliothek unter Linux durchgeführt?

Wie man eine Datei unter Linux ausführbar macht

So erstellen Sie einen Multiboot-USB in Linux und Windows

So listen Sie gemeinsam genutzte Bibliotheken auf, die von ausführbaren Dateien in Linux verwendet werden

So installieren Sie die PyBrain-Python-Bibliothek unter Linux

Wie mache ich eine Datei im Linux-Terminal ausführbar?

So erstellen Sie Minecraft Server auf Linux-Distributionen