1

您好,我有一个具有全局功能的程序,我想在运行时对其进行自定义。比如说,有许多版本的函数 foo() 分散在共享库中。现在,根据运行时检测到的系统配置,我想使用适当库中的函数。

文件加载器.cpp:

#include <dlfcn.h>
#include <iostream>

void __attribute__((weak)) foo();

    int main(int argc, char *argv[])
    {
        void* dl = dlopen("./other.so", RTLD_NOW | RTLD_GLOBAL);
        if (!dl)
        {
            std::cerr << dlerror() << std::endl;
            return 1;
        }
        if (foo)
        {
            foo();
        }
        else
        {
            std::cerr << "No foo?" << std::endl;
        }
        dlclose(dl);
        return 0;
    }

文件 other.cpp:

#include <iostream>

void foo()
{
    std::cout << "FOO!" << std::endl;
}

我用

g++ -Wall -fPIC -o loaded loader.cpp -ldl
g++ -Wall -fPIC -shared -o other.so  other.cpp 

但是,弱符号不会被覆盖。有什么提示吗?

4

2 回答 2

5

符号在引用它们的图像的加载期间被解析。因此,当您的可执行文件被加载时,对 foo 的引用已经被解析。稍后的 dlopen 不会重新绑定所有符号 - 它只会影响以后的加载。

您必须改用 dlsym,或设置 LD_PRELOAD:

martin@mira:/tmp$ LD_PRELOAD=/tmp/other.so ./loaded 
FOO!
于 2010-12-13T23:44:38.243 回答
0

您使用 g++ 编译了共享库。结果,函数的名称被破坏了:

$ nm -S other.so |grep foo
0000000000000690 000000000000002e T _Z3foov

如果您将其设为纯 C 代码并使用 gcc 而不是 g++ 进行编译,您会发现它按预期工作。

或者,将其定义如下:

extern "C" void foo()
{
  std::cout << "FOO!" << std::endl;
}
于 2014-09-16T14:58:07.780 回答