GNU/Linux >> Belajar Linux >  >> Linux

Cara membuat penundaan perpustakaan bersama dimuat di Linux

Pemuatan tunda BUKAN fitur runtime. MSVC++ mengimplementasikannya tanpa bantuan dari Windows. Dan seperti dlopen adalah satu-satunya cara di Linux, GetProcAddress adalah satu-satunya metode runtime di Windows.

Jadi, apa itu delay loading? Ini sangat sederhana:Setiap panggilan ke DLL harus melalui penunjuk (karena Anda tidak tahu di mana itu akan dimuat). Ini selalu ditangani oleh kompiler dan penghubung untuk Anda. Tetapi dengan pemuatan tunda, MSVC++ menyetel penunjuk ini awalnya ke stub yang memanggil LoadLibrary dan GetProcAddress untukmu.

Dentang dapat melakukan hal yang sama tanpa bantuan dari ld . Saat runtime, ini hanyalah dlopen biasa panggilan, dan Linux tidak dapat menentukan bahwa Clang telah memasukkannya.


Untuk menambah jawaban MSalters, seseorang dapat dengan mudah meniru pendekatan Windows untuk pemuatan lambat di Linux dengan membuat pustaka rintisan statis kecil yang akan mencoba dlopen diperlukan perpustakaan pada panggilan pertama ke salah satu fungsinya (memancarkan pesan diagnostik dan menghentikan jika dlopen gagal) dan kemudian meneruskan semua panggilan ke sana.

Pustaka rintisan semacam itu dapat ditulis dengan tangan, dihasilkan oleh skrip khusus proyek/pustaka atau dihasilkan oleh alat universal Implib.so:

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

Fungsionalitas ini dapat dicapai dengan cara portabel menggunakan pola desain Proxy.

Dalam kode mungkin terlihat seperti ini:

#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. Pengantar Pustaka Bersama Linux (Cara Membuat Pustaka Bersama)

  2. Bagaimana cara melihat daftar fungsi yang diekspor oleh perpustakaan bersama Linux?

  3. Bagaimana cara membuat cadangan diferensial di linux?

  1. Cara membuat komputer lama menjadi berguna kembali

  2. Cara Memasang Pustaka Ncurses Di Linux

  3. Linux – Bagaimana Membuat TR Mengetahui Karakter Non-ascii(unicode)?

  1. Bagaimana Membuat Direktori Bersama Dapat Diakses Oleh Sftp?

  2. C++ Dynamic Shared Library di Linux

  3. Cara menginisialisasi perpustakaan bersama di Linux