アプリケーションのプラグインシステムに推奨されるものは何ですか?

StackOverflow https://stackoverflow.com/questions/217172

質問

通常の”とはコンパイルされた言語(C#/ C / C ++ / D)でプラグインを実行する方法私は言語にとらわれないアプローチに特に興味がありますが、言語固有のものは受け入れられません。

とりあえず、“コンパイル時間”プラグインアプローチ(コードを含めるかどうか、すべてが機能する)は有効ですが、より動的なアプローチに移行できるものが優先されます。

ランタイムタイプについては、プラグイン/アプリインターフェースの設計よりも、プラグインのロードの仕組みに興味があります

編集:ところで、プラグインはマスターではなくスレーブになります。プラグインの基本的なアクションは、特定の状況下での「アクションを実行する」ために呼び出されます。そして、操作に必要なものを取得するために使用すべき環境オブジェクトが与えられます。

役に立ちましたか?

解決

コンパイル言語(コンパイルとは、プログラムが仮想マシンなしでネイティブ実行可能ファイルとして実行されることを意味します)では、何らかのプラットフォーム固有の共有ライブラリアプローチを使用する必要があります。 Windowsでは、これはDLLを使用することを意味します。

プラグインインターフェースを一連の関数(特定の名前、引数、呼び出し規則)の観点から定義します。次に、共有ライブラリ内の関数のアドレスをロードして、町に行きます。 Windowsでは、これは GetProcAddress()を使用することを意味します、そして戻り値をCの適切な型の関数ポインター、または使用している言語に相当するものにキャストします。

より望ましい場合とそうでない場合がある別のオプションは、ネイティブアプリケーション内から別の言語の仮想マシンを実行し、プラグインをその言語のコードにすることです。たとえば、CPythonを使用してPython VMを実行し、Pythonモジュールを動的にロードできます。

他のヒント

Mono.Addins は、.NETに適したソリューションのようです。リポジトリからプラグイン(またはアドイン)をダウンロードし、実行中のアセンブリに動的にロードできるAPIが含まれていると思います。

プラグインの難しい部分は、プラグインの検索、依存関係の解決、バージョンの問題の処理であることがわかりました。これらの問題をどのように処理するかは、あなたとプラグイン作成者にとって明らかです。これらの問題を間違えたとしても、痛みは終わりません。私は、プラグインを使用して何がうまく機能するかについてのアイデアを得るためのスクリプト言語とアプリケーションを見ます。

静的コンストラクタは多くの場合、「巧妙」です。悪い意味で。とにかく(動的な場合)一度に1つずつプラグインをロードする必要があるため(C / C ++:dlopen and friends under Linux)、同様に明示的に初期化することもできます。とりわけ、予想されるAPIなしでプラグインを拒否する機会を与える可能性があります。

注、プラグインにダイナミックロードライブラリを使用する必要はありません。他のメカニズムも使用できます:共有メモリ、ソケットなど...

それは本当に何をしたいかに依存します。 EmacsとGimpに見られる一般的なUnixパターンは、インタプリタコンポーネントがすべてを行うために使用する重要な機能を公開する小さなコンパイル済みコンポーネントで構成されるプログラムを記述することです。アプリの上に構築できる新しい機能を提供するプラグリンは簡単ですが、これを可能にするには、提供するプリミティブで非常に柔軟である必要があります。反対の極端な例では、複数の形式で保存できるフォトエディターを想像してください。ユーザーが独自のファイル形式ハンドラーを作成できるようにする必要があります。これには、コードで単純なプリミティブのセットを使用し、実行時に実装を選択する必要があります。ストレート(Unix)Cではdlopenを使用し、C ++ではextern Cを使用して、できることとdlopenを制限します。 Objective-Cには、それを行うためのクラスがあります。最初のケースでは、インタプリタを作成または再利用するため、自由に統治できます。

各プラグインが共通の機能セットの異なる実装をカプセル化するスレーブタイプのプラグインの場合、ホストアプリケーションに既知のプラグインフォルダーにDLLを配置するだけです(例:" c:\ program files \ myapp \プラグイン)、Reflectionを介してホストからDLLを呼び出します。

各DLLのインストール時に、ある種の精巧な登録プロセスをできますが、単純なプラグインワンフォルダーアプローチで問題を経験したことはありません。

編集:C#でこれを行うには、パブリッククラスをDLLに追加し(" Plugin"など)、必要な機能を実装します。ホストから、プラグインタイプのオブジェクトを作成し、そのメソッドを呼び出します(すべてReflectionを使用)。

無効なRegister(EventSource)を持つインターフェイスはうまく機能しているようです-ASP.NETの IHttpModule.Init(HttpApplication )の例。

これにより、アプリの作成者(EventSourceを制御する)は、必要に応じてIPluginインターフェイスを拡張することなく(IPluginEx、IPlugin2、IPlugin2Exなどにつながる)イベントを追加できます

(。NETで)私が使用したアプローチは、ホストに(Reflectionを介して)プラグインへの最初の呼び出しを行わせ、プラグインを開始し、プラグインが保存するホストへの参照を渡すことです。プラグインは、必要に応じて、ホスト上のメソッドも(リフレクション経由で)呼び出します。

ほとんどのプラグインでは、通常、呼び出しは他の方向に行われます(つまり、ホストは必要に応じてプラグインを呼び出します)。私の場合、プラグイン自体には、ホスト機能を利用するために必要なUI要素がありました。

低レベルモジュールの実装の問題(たとえば、Windows DLLと実装の問題)は別として、私が使用しているゲームエンジンはDLLにグローバル登録機能があり、プラグインディレクトリ内のすべてのdllでそれを見つけて呼び出します。 registartion関数は、機能を公開するために必要な簿記を行います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top