0

Fortran 95 ライブラリを中心に小さな C++ ラッパー共有ライブラリを作成しています。Fortran シンボルにはシンボル名が含まれているため、Fortran 関数を C++ 関数ポインターにロードする.ために使用する必要があります。dlsym

現在、ヘッダー ファイルに一連のグローバル関数ポインターがあります。

// test.h
extern void (*f)(int* arg);

そして、それらを対応する C++ ファイルに入力します。

// test.cc
void (*f))(int* = reinterpret_cast<void(*)(int*>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_");

質問:

  1. このようにすると、これらのポインターはいつ入力されますか?
  2. このライブラリをロードする実行可能ファイルにそれらがロードされていると想定できますか?
  3. 特に、実行可能ライブラリまたは他のライブラリで静的に作成されたオブジェクトでこれらの関数を使用できますか? それとも、これは静的初期化順序の大失敗に悩まされていますか?
  4. 上記の方法が正しくない場合、実行可能ファイルやその他のライブラリの静的オブジェクトで使用できるように、これらのポインターを設定する最もエレガントな方法は何ですか?

私は Solaris で Sun Studio コンパイラを使用していますが、それが違いを生むのであれば、Linux での GCC のソリューションにも興味があります。

4

1 に答える 1

1

線はどこにありますか

f = reinterpret_cast<void(*)(int*)>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_"));

で発生しtest.ccますか?ポインタは、行が実行されるときに初期化されます(もちろん、ポインタを含む関数がいつ呼び出されるかによって異なります)。それとも書くつもりでしたか

void (*f)(int* ) = reinterpret_cast<void(*)(int*>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_");

?この場合、ポインタは静的初期化中に初期化されます。つまり、静的オブジェクトのコンストラクターでポインターを使用しようとすると、初期化の順序に問題があります。

これに対する古典的な解決策は、ある種のシングルトンを使用することです。

struct LibraryPointers
{
    void (*f)(int* );
    //  ...
    static LibraryPointers const& instance()
private:
    LibraryPointers();
};

LibraryPointers const&
LibraryPointers::instance()
{
    static LibraryPointers theOneAndOnly;
    return theOneAndOnly;
}

LibraryPointers::LibraryPointers()
    : f( reinterpret_cast<void(*)(int*)>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_")) )
    , //  initialization of other pointers...
{
}

次に、この構造を使用してポインタのアドレスを取得するC++クラスでライブラリをラップします。

そして最後の注意:reinterpret_castあなたがやろうとしていることは合法ではなく、少なくとも正式にはそうではありません。(ただし、SunCCとg++の両方がそれを受け入れると思います。)Posixによると、関数へのポインターを取得する正しい方法は次のdlsymとおりです。

void (*f)(int* );
*reinterpret_cast<void**>(&f) = dlsym(...);

ただし、これは初期化には役立ちません。

于 2011-10-19T08:29:24.827 に答える