Загрузка двух экземпляров общей библиотеки без RTLD_PRIVATE или нескольких копий

В C ++ мне нужно запустить несколько экземпляров устаревших библиотек FORTRAN (над которыми я не имею никакого контроля), которые используют переменные COMMON BLOCK. Я могу успешно сделать это по рецепту Вопрос 3433522, где я создаю 2 физические копии библиотеки и загружаю их во время выполнения, используя dlopen (см. пример кода ниже).

Однако я хотел бы избежать создания двух физических копий библиотеки, поскольку она может быть довольно большой. Как предложено в Вопрос 3433522, с помощью RTLD_PRIVATE будет работать, но это не доступно (насколько я могу судить) в libgc с GCC. Я также исследовал с помощью RTLD_DEEPBIND скорее, чем RTLD_LOCAL но это не имеет значения. Любая идея, как это может быть достигнуто с помощью GCC?

Мой пример кода выглядит следующим образом:

  1. Makefile

    libgen.so: gen.f
    gfortran -Wall -shared -fPIC -o $@ $<
    
    libgen%.so: libgen.so
    cp $< $@
    
    run: run.cpp libgen1.so libgen2.so
    g++ -Wall -o $@ $< -L. -ldl
    
  2. gen.f

    C*********************************************************************
    
    C...GENDATA
    C...Common block of data.
    BLOCK DATA
    INTEGER NEVENT
    COMMON/GENDATA/NEVENT
    DATA NEVENT/0/
    END
    
    C*********************************************************************
    
    C...EVENT
    C...Simple example routine that produces an "event".
    
    SUBROUTINE GENERATE()
    INTEGER NEVENT
    COMMON/GENDATA/NEVENT
    NEVENT = NEVENT + 1
    PRINT *, NEVENT
    RETURN
    END
    
  3. run.cpp

    #include <iostream>
    #include <dlfcn.h>
    using namespace std;
    
    //==========================================================================
    
    // Methods to load and close dynamic libraries.
    
    //--------------------------------------------------------------------------
    
    // Load a symbol from a library.
    
    typedef void (*Symbol)();
    Symbol libSym(void *&lib, string libName, string symName) {
    
    Symbol sym(0);
    const char* error(0);
    
    // Load the library, if not loaded.
    if (!lib) {
    lib = dlopen(libName.c_str(), RTLD_NOW | RTLD_LOCAL);
    error = dlerror();
    }
    if (error) {
    cerr << "Error from libSym: " + string(error) + "\n";
    return sym;
    }
    dlerror();
    
    // Load the symbol.
    sym = (Symbol)dlsym(lib, symName.c_str());
    error = dlerror();
    if (error) cerr << "Error from libSym: " + string(error) + "\n";
    dlerror();
    return sym;
    
    }
    
    //--------------------------------------------------------------------------
    
    // Close a library.
    
    void libClose(void *&lib) {
    if (lib) {dlclose(lib); dlerror();}
    }
    
    //==========================================================================
    
    // The main program.
    
    //--------------------------------------------------------------------------
    
    int main() {
    
    // Load libraries.
    void *libgen1(0), *libgen2(0);
    cout << "Loading library 1.\n";
    void (*generate1)();
    generate1 = libSym(libgen1, "./libgen1.so", "generate_");
    if (!libgen1) return 1;
    cout << "Loading library 2.\n";
    void (*generate2)();
    generate2 = libSym(libgen2, "./libgen2.so", "generate_");
    if (!libgen2) return 1;
    
    // Generate events.
    cout << "Generating 1.\n";
    (*generate1)();
    cout << "Generating 1.\n";
    (*generate1)();
    cout << "Generating 2.\n";
    (*generate2)();
    
    // Close the libraries.
    libClose(libgen1);
    libClose(libgen2);
    return 0;
    
    }
    

3

Решение

Задача ещё не решена.

Другие решения


По вопросам рекламы [email protected]