4

在 C++ 中,我需要运行使用 COMMON BLOCK 变量的旧 FORTRAN 库(我无法控制)的多个实例。我可以按照问题 3433522的规定成功地做到这一点,在那里我创建了库的 2 个物理副本,并在运行时使用dlopen(参见下面的示例代码)加载这些副本。

但是,我想避免创建库的两个物理副本,因为它可能相当大。正如问题 3433522中所建议的,使用RTLD_PRIVATE会起作用,但这在libgcGCC 中不可用(据我所知)。我也研究过使用RTLD_DEEPBIND而不是RTLD_LOCAL,但这没有区别。知道如何使用 GCC 来实现这一点吗?

我的示例代码如下:

  1. 生成文件

    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. 运行.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;
    
    } 
    
4

0 回答 0