2011-01-21 4 views
5

私はC++プラグインインターフェイスをala How to create some class from dll(constructor in dll)?(с++) にする予定ですが、MinGWまたはBorland経由でDLLを作成するためにインターフェイスを使用し、DLLローダーがMSVC++でコンパイルされている可能性があります。問題。エクスポートされた関数だけがextern "C"と宣言されているので、なぜ機能しないのか分かりません。C++ DLLプラグインインターフェイス

アイデア?

答えて

10

コンパイラ(リリース/デバッグ)間で互換性があり、C++を使用したい場合は、もう少し努力する必要があります。

基本的には、基本的なデータ型と純粋な仮想クラスへのポインタを渡すことができます。これらのクラスにはデータメンバーが含まれてはならず、デストラクタはパブリックであってはならず、オーバーロードされた関数を持つべきではありません。

メモリは1つのDLLに割り当てられ、別のDLLで解放されてはなりません。これは例外を意味するものではなく、何らかの種類の参照カウントまたは戻り機構が必要です。

純粋な仮想クラス(別名「インタフェース」)内のすべてのメソッドは、呼び出し規約(私はstdcallを好むでしょう)でマークする必要があります。

ダイナミックキャストは不可能なので、COMのQueryInterfaceのようなトリックを実行するには、すべてのインターフェイスにいくつかの機能が必要な場合があります。

これは、win32上のほとんどのコンパイラがCOM互換性を持ち、COM互換性のある方法で同じ問題を解決しようとしているために機能します。最初のインターフェイスを取得するには、dllからエクスポートされたプレーンなC関数が必要です。

C関数とCデータ型を使用するだけであれば、すべてが同様に機能します。しかし、あなたはクラスなしでCに制限されています&継承。

私は役立つことを願っています。


名前マングリングは問題ではありません。

第一:STDCALLとVSで、あなたが再マップする必要があります:あなたはCのデータ型とCの関数を使用する場合は、すべてのものが定義されている、何の名前マングリング(例外はありませんLinkerディレクティブを介して "通常の" Cの名前への名前)

第2の:クラス内のメソッドはエクスポートされないため、マングリングされません。純粋な仮想クラスへのポインタ(別名「インタフェース」)を介してメソッドを呼び出します。これはオフセットと名前を使用しません。 vtbl内のデストラクタの位置は私が知る限り固定されていないので、まだデストラクタを使用することはできません。


構造体を関数/メソッドに渡す場合は、必ずアライメントを固定してください。異なるコンパイラ間では定義されていません。

+0

名前のマングリングはどうですか?異なるコンパイラのデストラクタでも同じでしょうか? – ssmir

+0

これは、vtableのシンボルが異なる可能性があり、メソッドのオフセットが異なる可能性があるため、別のコンパイラで作成されたプラグインを使用できないことを意味します。 – ssmir

+0

しかし、vtable構造体はC++標準で定義されていませんか?それで、別の(コンパチブルな)コンパイラを使うのは問題ありません。 – Robert

0

標準のextern C関数を使用してClassFactoryを作成する方法が考えられます。 dllが有効なプラグインであることを明らかにしなければならない固定(またはそれ以上の)エントリーポイントについて、いくつかの議論があります。

+0

はい、エクスポートされる関数はextern "C" Plugin * GetPluginObject()だけです。私は前にこれをやったことがありますが、DLLのコントロールがありました(つまり、MinGW/Borlandなどを式に入れない) – Robert

+0

GetPluginObjectがいくつかのクラスのistanceを返すのはどうですか?異なるコンパイラの実装間で互換性のあるVTableはありませんか?私はMS COMがこれらのアイデアを活用していると思います... –

+0

彼らは、ある程度拡張しています。上記の私の答えを参照してください。 –