1

こんにちは、実行時にカスタマイズしたいグローバル関数を持つプログラムがあります。たとえば、関数 foo() には多くのバージョンが共有ライブラリに散らばっています。ここで、実行時に検出されたシステム構成に基づいて、適切なライブラリの関数を使用したいと思います。

ファイル loader.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 コードにして、g++ ではなく gcc でコンパイルすると、期待どおりに動作することがわかります。

または、次のように定義します。

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