在C ++中,可以从动态库中访问外部定义的全局变量吗?
我在头文件中声明了一个全局变量,如下所示;
文件名:TestVariable.hpp
#ifndef TESTVARIABLE_HPP
#define TESTVARIABLE_HPP
extern
int testVariable;
#endif
然后在源代码文件中定义如下;
文件名:TestVariable.cpp
int testVariable;
构成我的动态库的源代码如下:
文件名:Plugin.cpp
#include <TestVariable.hpp>
#ifdef __cplusplus
extern "C" {
#endif
void *
__attribute__((constructor))
loadLibrary
(
void
)
{
testVariable = 100;
}
void *
__attribute__((destructor))
unloadLibrary
(
void
)
{
}
#ifdef __cplusplus
}
#endif
我的主要功能定义如下;
文件名:main.cpp
#include <iostream>
#include <dlfcn.h>
// dlopen
#include <TestVariable.hpp>
using std::cout;
using std::endl;
int main(void)
{
void * libHandle_p = NULL;
cout << "Test variable = " << testVariable << endl;
// Load the dynamic library.
libHandle_p = dlopen("./.libs/libPlugin.so", RTLD_LAZY);
if (libHandle_p == NULL)
{
cout << "Error loading library" << endl;
return(-1);
}
cout << "Test variable = " << testVariable << endl;
return(0);
}
我可以使用GNU Autotools,g ++和ld正确地编译和链接所有代码(并且没有任何警告),但是当我运行生成的二进制可执行文件时,它无法删除动态库文件。但是,如果我注释掉包含函数 loadLibrary 主体的唯一一行代码,然后重新编译和链接,程序就能正常工作!
如果我不知道更好,我会说当调用dlopen(库)时,库无法解析对全局变量 testVariable 的引用,这就是导致dlopen操作失败。链接类型和/或名称修改可能与此问题有关吗?
如果我在生成的动态库上运行Linux nm实用程序,它会通知我符号 testVariable 未定义,即“U”。如果我在二进制可执行文件上运行nm实用程序,它会通知我符号 testVariable 存在并位于未初始化的数据部分,即“B”。那么为什么在加载动态库时dlopen不能解析这个符号呢?
我只从源文件 Plugin.cpp 生成动态库。二进制可执行文件是从2个源代码文件 main.cpp 和 TestVariable.cpp 生成的。
有人可以帮忙。我可以发誓答案是盯着我,但我只是没有看到它。
提前致谢。
答案 0 :(得分:2)
似乎我已经解决了我自己的问题。在编译二进制可执行文件(而不是动态库)时将以下参数传递给GNU g ++编译器修复了问题;
-Wl,--export-dynamic
它的作用是因为它强制链接器将符号 testVariable 添加到动态符号表中,并且根据ld(GNU链接器)的手册页,动态符号表包含一组在运行时对动态对象(在本例中为我的库)可见的符号。
很抱歉给您带来不便。