Adobe Photoshopを使用したことがありますか?素人の場合、プラグインは外部からアプリケーションに提供されるコードブロックのみです(たとえば、DLL)。プラグインと通常のDLLの違いは、プラグインが親アプリケーションの機能を拡張できることです。たとえば、Photoshop自体には大量の画像処理機能がありません。プラグインを追加すると、ぼかし、スポット、その他すべてのスタイルなどの素晴らしい効果が得られ、それらのいずれも親アプリケーション自体を持っていません。
これは画像処理プログラムに非常に適していますが、プラグインをサポートする商用アプリケーションを完了するために多くの努力を費やす必要があるのはなぜですか?たとえば、アプリケーションがいくつかのレポートを生成すると仮定します。顧客は間違いなく更新を求めたり、新しいレポートを追加したりします。それほど多くのようなソリューションであるレポートスミスなどの外部レポートジェネレーターを使用できます。これは、追加ファイルを公開する必要があります。ユーザー向けの追加トレーニングなどが必要です。 QuickReportを使用することもできますが、これにより、バージョンのコントロールの悪夢になります。フォントを変更するたびにアプリケーションを再構築する場合。
ただし、プラグインにレポートを作成する限り、使用できます。新しいレポートが必要ですか?問題ありません。DLLをインストールするだけで、次回アプリケーションが開始されたときに表示されます。別の例は、外部デバイス(バーコードスキャナーなど)からのデータを処理するアプリケーションです。プラグインとして各デバイスインターフェイス処理ルーチンを記述することにより、親アプリケーションに変更を加えることなく、最大のスケーラビリティを実現できます。
はじめる
コードの作成を開始する前の最も重要なことは、アプリケーションが拡張する必要がある機能を把握することです。これは、プラグインが特定のインターフェイスを介して親アプリケーションと対話するため、ニーズに応じて定義されます。この記事では、3つのプラグインを構築して、プラグインが親アプリケーションと対話するいくつかの方法を紹介します。
プラグインをDLLにします。ただし、これを行う前に、シェルを作成してロードしてテストする必要があります。図1は、最初のプラグインがロードされた後のテストプログラムを示しています。最初のプラグインは大きなものを達成しません。実際、それが行うのは、それ自体を説明する文字列を返すことだけです。ただし、重要なポイントを確認します。プラグインアプリケーションの有無にかかわらず適切に機能します。プラグインがない場合、インストールされたプラグインのリストには表示されませんが、アプリケーションはまだ機能を実行できます。
プラグインシェルと通常のアプリケーションの唯一の違いは、Project SourceファイルのSharememユニットであり、使用句とプラグインファイルをロードするコードに表示されます。それ自体と子のdllの間に文字列パラメーターを渡すアプリケーションが必要です。このシェルをテストするには、delphimm.dllファイルをDelphi/binディレクトリからパス環境変数またはアプリケーションがあるディレクトリに含まれるパスにコピーする必要があります。ファイルは、最終バージョンがリリースされたときに同時に配布する必要があります。
プラグインは、メインウィンドウのFormCreateイベントで呼び出されるLoadPluginsプロセスを介してこのテストシェルにロードされます。図2を参照してください。このプロセスでは、FindFirstとFindNext関数を使用して、アプリケーションが配置されているディレクトリ内のプラグインファイルを見つけます。ファイルを見つけた後、図3に示すLoadPluginsプロセスを使用してロードします。
{アプリケーションディレクトリでプラグインファイルを見つける}
手順tfrmmain.loadplugins;
var
SR:TsearchRec;
パス:文字列;
見つかった:整数;
始める
パス:= extractfilepath(application.exename);
試す
見つかった:= findFirst(path + cplugin_mask、0、sr);
見つかった= 0が始まります
LoadPlugin(SR);
見つかった:= findnext(sr);
終わり;
ついに
findclose(sr);
終わり;
終わり;
{指定されたプラグインDLLをロードします。
手順tfrmmain.loadplugin(sr:tsearchrec);
var
説明:文字列;
Libhandle:整数;
descripeproc:tplugindesscribe;
始める
libhandle:= loadlibrary(pchar(sr.name));
libhandle $#@60; $@62;
始める
descripeproc:= getProcAddress(libhandle、cplugin_describe);
割り当てられている場合(describeproc)
説明proc(description);
memplugins.lines.add(説明);
終わり
それ以外
始める
mesagedlg( 'file "' + sr.Name + '"は有効なプラグインではありません。'、
mtinformation、[mbok]、0);
終わり;
終わり
それ以外
MESSAGEDLG( 'エラーが発生し、プラグインのロード "' +
sr.Name + '"。'、mterror、[mbok]、0);
終わり;
LoadPluginメソッドは、プラグインメカニズムのコアを示しています。まず、プラグインはDLLとして記述されます。第二に、LoadLibrary APIを介して動的にロードされます。 DLLがロードされると、含まれる手順と機能にアクセスする方法が必要です。 APIコールGetProcAddressはこのメカニズムを提供し、必要なルーチンへのポインターを返します。私たちの簡単なデモンストレーションでは、プラグインには定数CPLUGIN_DEScribeで指定されたDecribePluginと呼ばれる手順のみが含まれています(手順名の場合は非常に重要であり、GetProcAddressに渡された名前はDLLに含まれるルーチン名とまったく同じでなければなりません) 。 DLLに要求されたルーチンが見つからない場合、getProcaddreeはnilを返します。そのため、割り当てられた関数を使用して返品値を決定することに同意します。
ポインターを使いやすい方法で機能に保存するには、使用される変数の特定のタイプを作成する必要があります。 GetProcAddressの返品値は、変数で保存されていることに注意してください。DescrestEprocは、tplugIndesscribeタイプに属します。これがその声明です:
タイプ
tplugindescribe = procedure(var desc:string);
手順はDLL内に存在するため、標準のコール変換を介してすべてのエクスポートルーチンをコンパイルするため、STDCALLインジケータが必要です。このプロセスでは、VARパラメーターを使用します。これには、プロセスが返されたときにプラグインの説明が含まれます。
取得したプロセスを呼び出すには、アドレスをプロセス名として保存する変数を使用して、パラメーターが続きます。私たちの場合、声明:
説明proc(説明)
プラグインで取得された説明プロセスが呼び出され、説明変数にはプラグインの機能を説明する文字列が入力されます。
建設プラグイン
親アプリケーションを作成しました。読み込みたいプラグインを作成する時が来ました。プラグインファイルは標準のDelphi DLLであるため、Delphi IDEから新しいDLLプロジェクトを作成して保存します。エクスポートされたプラグイン関数は文字列パラメーターを使用するため、Sharemenユニットはプロジェクトの使用節に最初に配置する必要があります。図4に、単純なプラグインのプロジェクトソースファイルを示します。
用途
Sharemem、sysutils、classes、
'main.pas'のメイン;
{$ e plg。}
輸出
dectureplugin;
始める
終わり。
プラグインはDLLファイルですが、.dll拡張子を与える必要はありません。実際、1つの理由は、拡張機能を変更する理由を提供するのに十分です。親アプリケーションがファイルをロードするファイルを探したとき、新しい拡張機能は特定のファイルマスクとして機能します。別の拡張機能(例では *.plgを使用)を使用することにより、アプリケーションが対応するファイルのみをロードすることを確信できます。インジケータ$ xをコンパイルすると、この変更を達成できます。または、[プロジェクトオプション]ダイアログボックスのアプリケーションページから拡張機能を設定できます。
最初の例プラグインのコードは非常に簡単です。図5は、新しいユニットに含まれるコードを示しています。 DescripLuginプロトタイプは、シェルアプリケーションのtplugindescribeタイプと一致しており、追加のエクスポート予約ワードを使用してプロセスがエクスポートされることを指定することに注意してください。エクスポートされたプロセス名は、メインプロジェクトソースコードのエクスポートセクション(図4にリストされています)にも表示されます。
ユニットメイン;
インタフェース
手順decturseplugin(var desc:string);
エクスポート;
実装
手順decturseplugin(var desc:string);
始める
DESC:= 'テストプラグインV1.00';
終わり;
終わり。
このプラグインをテストする前に、メインアプリケーションのパスにコピーします。最も簡単な方法は、ホームディレクトリのサブディレクトリにプラグインを作成し、メインパスに出力パスを設定することです(プロジェクトオプションのディレクトリ/条件付けダイアログボックスもこの設定に使用できます)。
デバッグ
次に、Delphi 3:The DellsからIDEからDLLをデバッグする機能を紹介します。 DLLプロジェクトでは、[パラメート]ダイアログボックスを使用して、ホストアプリケーションとしてプログラムを指定できます。これは、DLLを呼び出すアプリケーションへのパスです。次に、DLLコードでブレークポイントを設定し、F9を押して実行することができます。通常のアプリケーションで実行するのと同じように。 Delphiは、指定されたホストプログラムを実行し、DLLをデバッグ情報でコンパイルすることにより、DLLコードのブレークポイントに誘導します。