在C ++中,可以从动态库中访问外部定义的全局变量吗?

时间:2011-03-11 09:39:17

标签: c++ linux dlopen

在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 生成的。

有人可以帮忙。我可以发誓答案是盯着我,但我只是没有看到它。

提前致谢。

1 个答案:

答案 0 :(得分:2)

似乎我已经解决了我自己的问题。在编译二进制可执行文件(而不是动态库)时将以下参数传递给GNU g ++编译器修复了问题;

-Wl,--export-dynamic

它的作用是因为它强制链接器将符号 testVariable 添加到动态符号表中,并且根据ld(GNU链接器)的手册页,动态符号表包含一组在运行时对动态对象(在本例中为我的库)可见的符号。

很抱歉给您带来不便。