4

私は、アプリケーションに実行時にロードできるC++のダイナミックライブラリを開発しようとしています。ようやく動作しましたが、少し醜いです。C++クラスへのポインタを引数として取る関数があります。これは次のようになります。

bool registerGrindPlugin( Grind::PluginManager* mgr );

しかしもちろん、それは次のようにエクスポートされています:

_Z19registerGrindPluginPN5Grind13PluginManagerE

単純な関数で.cファイルを試したところ、「registerGrindPlugin」として正常にエクスポートされましたが、もちろん、引数としてC++クラスを渡すことはできません。

Soo ...私の質問は、エクスポートされたシンボルのマングルを解除またはエイリアス化して、dlsym呼び出しでZ19registerGrindPluginPN5Grind13PluginManagerEのような怪物を使用する必要がないようにする方法はありますか?

リンカオプションとして-alias_listについて何かを見ましたが、XCodeでそれを使用する方法を完全には理解していません。それが解決策である場合、誰かがこれを使用する方法についてもう少し詳細を提供できますか?

4

3 に答える 3

4

あなたがそれをやろうとしている方法は、長期にわたって機能することはありません。

特定のC++マングリング/デマングリングアルゴリズムを当てにすることはできません。異なるコンパイラー(そして同じコンパイラーの異なるバージョンでさえ)は異なるものを使用しました。したがって、これを実行して、新しいバージョンのXcodeに切り替えると、悪い状況に置かれる可能性があります。

また、C++には脆弱なバイナリインターフェイスの問題があります。これを回避するには、Grind :: PluginManagerインスタンスの内部で、作成からメンバーアクセス、削除までのすべての操作を同じダイナミックライブラリで行う必要があります。

これらの問題を解決することは、ObjectiveCのメッセージングシステムとWindowsOLEシステムの背後にある理論的根拠の一部です。

C ++ソリューションは、ラッパーシステムを使用することです。

まず、Grind ::PluginManager*の代わりとなる不透明なポインタータイプを定義する必要があります。C言語のCocoaバインディングはこれをたくさん行います。

typedef void* MyGrindPlugInManagerOpaqueHandle;

次に、ダイナミックライブラリの外部からGrind :: PluginManagerで実行する操作ごとに、マングルされていextern "C"ないCバインディングを使用して関数を定義する必要があります。これは、これらの不透明なポインターの1つを引数として取ります。例えば:

#ifdef __cplusplus
extern "C" {
#endif

void foo_wrapper(MyGrindPlugInManagerOpaqueHandle *bar);

#ifdef __cplusplus
}
#endif

第三に、C++ファイルでの実装は次のようになります。

void foo_wrapper(MyGrindPlugInManagerOpaqueHandle *bar)
{
    Grind::PluginManager* baz = (Grind::PluginManager*)bar;
    baz->foo();
}
于 2010-12-22T06:16:39.350 に答える
2

通常、プラグインインターフェイスは、c-namingと呼び出し規約で定義されます。名前マングリングは、コンパイラに依存する可能性があります(非標準)。

したがって、最も簡単な解決策は、インターフェイス関数を定義し、それを次のように宣言することですextern "C"

extern "C"  {
    bool registerGrindPlugin( Grind::PluginManager* mgr );
}

Grid::PluginManagerをvoid*タイプと内部キャストに置き換える必要がある場合があります。これは、仮想関数を持つクラスではなく、単純な構造である必要があります。

マングルされた名前の処理を主張する場合は、OSXでも利用可能なgnuユーティリティである「c++filt」のソースコードを確認できます。

于 2010-12-22T05:49:39.973 に答える
1

プロジェクトウィンドウの左側のペインでビルドしようとしているターゲットを選択し、[情報]ボタンをクリックすると、XCodeでリンカーフラグを設定できます。[ビルド]タブには、[その他のリンカーフラグ]と呼ばれるものを含む、リンカー設定のセクション全体があります。これにより、試行するリンカーオプションを指定できるようになります。

于 2010-12-22T05:47:27.583 に答える