1

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

当面は、「コンパイル時」のプラグイン アプローチ (コードを含めるかどうかだけですべてが機能する) が有効ですが、より動的なアプローチに移行できるものが優先されます。

ランタイム タイプに関しては、プラグイン/アプリ インターフェイスの設計よりも、プラグインのロードの仕組みなどに関心があります。

編集:ところで、プラグインはマスターではなくスレーブになります。プラグインの基本的なアクションは、特定の状況下で「自分の仕事をする」ように要求され、操作に必要なものを取得するために使用する環境オブジェクトが与えられることです。

4

8 に答える 8

3

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

于 2008-10-20T00:06:12.507 に答える
2

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

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

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

于 2008-10-20T00:48:10.533 に答える
1

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

于 2008-10-20T01:05:51.340 に答える
1

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

静的コンストラクターは、多くの場合、悪い意味で「賢い」ものです。いずれにせよ (C/C++: Linux では dlopen とその仲間) プラグインを一度に 1 つずつロードする必要があるため (動的な場合)、そうするときにプラグインを明示的に初期化することもできます。とりわけ、期待される API のないプラグインを拒否する機会が得られる可能性があります。

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

于 2008-10-20T00:01:45.213 に答える
1

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

各 DLL をインストールするときに、ある種の複雑な登録プロセスを実行できますが、単純なプラグインを 1 つのフォルダーに配置する方法で問題を経験したことはありません。

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

于 2008-10-20T03:32:30.267 に答える
0

void Register(EventSource) を持つインターフェイスはうまく機能しているようです。例については、ASP.NET のIHttpModule.Init(HttpApplication ) を参照してください。

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

于 2008-10-19T23:46:00.940 に答える
0

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

于 2008-10-20T01:10:27.650 に答える
0

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

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

于 2008-10-20T00:36:27.983 に答える