环境:Intel Linux、Red Hat 5。 编译器:gcc 3.4.6 (旧东西,具有严重基础设施的遗留环境,抱歉)
我有一个特定共享库的多个版本(称之为“shared_lib.so”),它源自 Fortran,其中包含一个 COMMON block 和引用该 COMMON 中的变量的各种计算。
我需要能够(从最终产品可执行文件中其他地方的 C 代码)在运行时使用 dlclose() 和 dlopen() 在这个库的版本之间切换(其中所有版本的 COMMON 内容都是相同的) .在某些情况下,相同的 COMMON 也出现在作为静态库(称为“static_lib.a”)的一部分的代码中,该库也链接到可执行文件中,并且与我的项目分开维护,但具有与我的共享图书馆。
我似乎看到 COMMON 的多个实例在可执行文件中结束,并且(更重要的是)静态库实例中的变量值与“相同”的值之间没有联系”实例中的变量来自使用 dlopen() 引入的共享库。
总而言之,我需要的是(在整个可执行文件中)加载 dlopen() 的 shared_lib.so 能够在 COMMON ABC 中设置/使用变量 XYZ,以及 static_lib.a 中的代码设置/使用 XYZ,并使其成为 XYZ 的同一个实例,或者至少使两者保持同步。这可能吗?
我对 shared_lib.so 中源代码的编译命令的形式是:
g77 –c –g –m32 -fPIC –o shared_src.o shared_src.f
我构建 shared_lib.so 的命令是这样的形式:
gcc -g -m32 -fPIC -shared -o shared_lib.so *.o
我构建可执行文件的命令是这样的形式:
gcc –g -m32 –rdynamic –o exec exec.o static_lib.a shared_lib.so –lm –ldl –lg2c
我需要从以下形式的 C 代码中做一些事情:
handle1 = dlopen ("shared_lib.so", RTLD_NOLOAD);
dlclose (handle1);
handle2 = dlopen ("shared_lib2.so", RTLD_NOW | RTLD_GLOBAL);
...
对于所需的变量,初始启动配置似乎确实可以正常运行,但后续 dlclose() 和 dlopen() 序列的结果却没有。也许潜在的问题是 dlopen() 缺少 gcc 在链接时拥有的一些智能。
最佳答案
简答
您是否/可以使用 -fPIC
重新编译可执行文件?我发现有必要使用 -fPIC
编译共享库和可执行文件,以便正确识别 COMMON
block 。
长答案
我最近遇到了一个与可执行文件和 FORTRAN 共享库之间共享的 COMMON block 稍微类似的问题。但是,我使用的是 Intel 编译器,而不是 GNU
编译器。可执行文件是 C/C++
和 FORTRAN
的混合体。
代码的现有(工作)Windows 版本通过 DLLEXPORT
/DLLIMPORT
ATTRIBUTE 指令共享可执行文件和 DLL 之间的公共(public) block 来工作。根据 Intel 编译器文档,Linux 无法识别这些属性指令。实际上,Linux Intel 编译器只会为这些指令生成警告。
将代码从 Windows 转换到 Linux 的主要变化是将 Windows LoadLibrary
和 GetProcAddress
替换为 Linux 的 dlopen
和 dlsym
例程,分别使用 #ifdef
部分。共享库使用 -fpic
编译并与 -shared
链接。
虽然共享库是使用 -fpic
编译的,但可执行文件不是。当运行以这种方式编译的代码时,通过子程序调用传递给共享库的变量被正确传递,但是,COMMON
block 变量设置不正确(或未初始化)。
无奈之下,我终于尝试使用 -fpic
编译器选项编译可执行文件本身,然后在共享库中正确识别了 COMMON
block 。
关于c - 可见性、Fortran 公共(public)变量、共享库的运行时加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27006442/