在 C++ 中,我需要运行使用 COMMON BLOCK 变量的旧 FORTRAN 库(我无法控制)的多个实例。我可以按照问题 3433522的规定成功地做到这一点,在那里我创建了库的 2 个物理副本,并在运行时使用dlopen
(参见下面的示例代码)加载这些副本。
但是,我想避免创建库的两个物理副本,因为它可能相当大。正如问题 3433522中所建议的,使用RTLD_PRIVATE
会起作用,但这在libgc
GCC 中不可用(据我所知)。我也研究过使用RTLD_DEEPBIND
而不是RTLD_LOCAL
,但这没有区别。知道如何使用 GCC 来实现这一点吗?
我的示例代码如下:
生成文件
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
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
运行.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; }