共有ライブラリ(Solaris、Sun Studio)にグローバル機能ポインターを入力する
-
26-10-2019 - |
質問
Fortran 95ライブラリの周りに小さなC ++ラッパー共有ライブラリを作成しています。 Fortranシンボルには含まれているため .
シンボル名では、使用する必要があります dlsym
Fortran関数をC ++関数ポインターにロードします。
現在、ヘッダーファイルにはグローバルな機能ポインターがたくさんあります。
// test.h
extern void (*f)(int* arg);
そして、私はそれらを対応するC ++ファイルに入力します:
// test.cc
void (*f))(int* = reinterpret_cast<void(*)(int*>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_");
質問:
- 私がこのようにそれをするならば、 これらのポインターはいつ人になりますか?
- このライブラリをロードする実行可能ファイルにロードされると仮定できますか?
- 特に、 これらの関数を静的に作成したオブジェクトで使用できますか? 私の実行可能または他の図書館で?または、これはに苦しんでいますか 静的イタリゼーション順序Fiasco?
- 上記の方法が正しくない場合、 これらのポインターに住む最もエレガントな方法は何ですか 実行可能ファイルやその他のライブラリの静的オブジェクトで使用できるように?
SolarisでSun Studioコンパイラを使用していますが、それが違いを生む場合は、LinuxのGCCのソリューションにも興味があります。
解決
ラインはどこにありますか
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
少なくとも正式にはそうではありません。 (ただし、Sun CCとG ++の両方がそれを受け入れると思います。)Posixによると、からのポインターを機能させる正しい方法は dlsym
だろう:
void (*f)(int* );
*reinterpret_cast<void**>(&f) = dlsym(...);
ただし、これは初期化に役立ちません。
所属していません StackOverflow