インテル® Fortran コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス

COM サーバーの詳細 (Windows*)

このトピックは、Windows* にのみ適用されます。

このセクションでは、Fortran COM サーバーに関する次のトピックについて説明します。

COM サーバーの種類 (DLL または EXE) の選択

DLL (インプロセス) COM サーバーと EXE (アウトオブプロセス) COM サーバーを選択する際の基本的なトレードオフは、パフォーマンスと安定性です。

パフォーマンスと安定性のトレードオフに加えて、次の点も考慮する必要があります。

DLL サーバーを代理サーバーにロードして、EXE サーバーのメリットを利用することができます。詳細は、次のセクションで説明します。

DLL 代理サーバー

インプロセス DLL サーバーは、代理サーバーを使用して、別のプロセスで実行することができます。代理サーバーは別のプロセスとして実行され、DLL サーバーをロードして、DLL サーバーがローカルサーバーとして動作するために必要なすべてのメカニズムを提供します。Windows* では、DLLHOST.EXE という名前の標準の代理サーバーが提供されています。代理サーバーを使用する最大のメリットは、障害を分離できることです。つまり、サーバーがクラッシュしても、クライアントはクラッシュしません。また、その逆についても同じことがいえます。ただし、パフォーマンスに影響を与えます。別のアプリケーションでのメソッドの実行は、DLL と比べると、著しいパフォーマンスのオーバーヘッドが発生します。

DLL サーバーは、システム・レジストリーの項目 (AppID) に関連付けることで、代理サーバーと関連付けられます。AppID は GUID です。標準の代理サーバーを使用する場合は、DLL クラスの CLSID を AppID として使用するか、または新しく生成した GUID を使用することができます。新しい GUID を生成する場合は、Developer Studio Tools サブディレクトリーにある GUIDGEN.EXE を使用します。

  1. クラスの HKEY_CLASSES_ROOT\CLSID\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx} キーに、CLSID の値を使用して AppID を追加します。サンプル・プロジェクトの AddingMachine クラスでは、レジストリー・キーは HKEY_CLASSES_ROOT\CLSID\{904245FC-DD6D-11D3-9835-0000F875E193} となり、AppID の値は {904245FC-DD6D-11D3-9835-0000F875E193} となります。

  2. HKEY_CLASSES_ROOT\AppID キーに、AppID を使用して新しいキーを追加します。サンプル・プロジェクトの AddingMachine クラスでは、レジストリー・キーは HKEY_CLASSES_ROOT\AppID\{904245FC-DD6D-11D3-9835-0000F875E193} となります。キーのデフォルト値をクラス名として使用します (例: AddingMachine Class)。値に、空の文字列を持つ DllSurrogate 項目を追加します。

クライアントは、インプロセス DLL サーバーをロードせずに代理サーバーを使用するために、CLSCTX_INPROC_SERVER ではなく、CLSCTX_LOCAL_SERVER を要求する必要があります。メソッドが別々のプロセスから呼び出されるため、代理サーバーを使用するには、DLL サーバーのプロキシー/スタブを登録する必要があります。プロキシー/スタブについての情報は、「マーシャリング、プロキシー、およびスタブ」を参照してください。

カスタム代理サーバーを作成することもできます。詳細は、Windows* Platform SDK のドキュメントを参照してください。

ウィザードを使用したコードの生成

COM サーバーウィザードは、templates という名前のプロジェクト・サブディレクトリーにあるファイルから、プロジェクトのコードを生成します。project-name.hie ファイルには、非公開のテキスト言語で記述された COM サーバーの定義が含まれています。project-name.hie ファイルは手動で編集しないでください。ウィザードによって編集されます。

templates ディレクトリーにあるその他のファイルのほとんどは、プロジェクト用に生成されたソースファイルのテンプレートです。これらのテンプレートには、生成されるソースに "そのまま" コピーされるソースコードと、定義する COM サーバー固有のコードを生成する際に、ウィザードが使用する埋め込みディレクティブが含まれています。ディレクティブは project-name.hie ファイルの情報を使用します。ディレクティブは、非公開で、変更されることがあります。

新しい Fortran COM サーバー・プロジェクトを作成する場合、ウィザードは templates ディレクトリーを作成して、Fortran COM サーバーのテンプレート・ディレクトリー (...\Intel Fortran\Templates\COMServer) からテンプレートをコピーします。

Fortran COM サーバーのテンプレート・ディレクトリー内のファイルは、バージョンによって異なりますが、プロジェクトの templates ディレクトリー内のファイルは自動的に更新されません。例えば、インテル® Visual Fortran コンパイラー 13.0 を使用して COM サーバーを作成した場合、次のリリース (バージョン 13.1) に更新されたテンプレートが含まれていても、COM サーバー・プロジェクトのテンプレートは、新しい 13.1 のテンプレートに更新されません。サーバーの定義を変更しても、プロジェクトはそのサーバーの作成時に作成されたテンプレートを使用し続けます。これは、開発およびテスト済みのプロジェクトに新しく別のコードを追加しなくても良いというメリットがあります。

ただし、次のように、プロジェクトで使用するテンプレートを変更したほうが良い場合もあります。

テンプレートを変更するメリットは、ウィザードによって生成されたコードをカスタマイズできることです。しかし、次の点に注意してください。

スレッド化モデル

ウィザードは、DLL COM サーバーで作成するクラスにおいて Apartment (集合) と Single (単一) の 2 つの COM スレッド化モデルをサポートしています。デフォルトでは、Apartment (集合) スレッド化モデル (STA: Single Threaded Apartment) を使用します。Apartment (集合) スレッド化モデルの基本的な規則は次のとおりです。

クラスのオブジェクト間でグローバルデータを共有している場合、スレッド同期プリミティブを使用して、そのグローバルデータへのアクセスを保護する必要があります。これは、クラスの 2 つのインスタンスが別々のスレッドで実行される可能性があるためです。クラスの派生型フィールドである per-object インスタンス・データは、COM メカニズムによって同時アクセスから保護されています。ただし、オブジェクトが自身の再入可能な呼び出しを引き起こす別のオブジェクトを呼び出す場合は除きます。

Single (単一) スレッド化モデルを使用するクラスでは、クラスのグローバルデータおよび per-object データへの同時アクセスについて考慮する必要はありません。すべてのオブジェクトは、単一のスレッドで作成されるため、同時に 1 つのオブジェクトのみ実行することができます。

ウィザードによって生成される EXE COM サーバーは単一スレッドです。すべてのメソッドの呼び出しは、サーバーのメッセージキューによって順次実行されます。このため、EXE サーバーでは、クラスのグローバルデータおよび per-object データへの同時アクセスについて考慮する必要はありません。

COM スレッド化モデルの詳細については、Windows* Platform SDK のドキュメントを参照してください。

マーシャリング、プロキシー、およびスタブ

COM は、(EXE サーバーまたは DLL 代用サーバーで) 別のプロセスでのオブジェクトの使用をサポートしています。また、マーシャリング、プロキシー、およびスタブを使用する上記のスレッド化モデルの使用もサポートしています。このセクションでは、マーシャリング、プロキシー、およびスタブの概要について説明します。

マーシャリングとは、メソッドの呼び出しに必要な引数を読み出し、別の実行コンテキスト (スレッド、プロセス、マシンなど) へ転送するために準備する処理です。マーシャリングはプロキシーによって行われます。クライアント側からは、プロキシーとオブジェクトのインターフェイスは同じに見えます。プロキシーの役割は、オブジェクトがクライアントと同じ実行コンテキスト内にあるかのように見せることです。

プロキシーにより、クライアント・コードで実際のオブジェクトの場所を考慮する必要がなくなります。プロキシーはメソッド引数をマーシャリングして、サーバー内のオブジェクトに関連付けられたスタブへ転送します。スタブは引数をアンマーシャリングして、サーバーでメソッドを呼び出します。サーバー側からは、同一の実行コンテキスト内のクライアントから呼び出された場合と同じように見えます。インプロセス DLL サーバー以外のサーバーでは、常にプロキシー/スタブのペアが必要です。インプロセス DLL サーバーでは、クライアントとオブジェクトが別の集合にある場合、プロキシー/スタブのペアが必要になります。

サーバーにプロキシー/スタブのペアを割り当てる方法は 3 つあります。

タイプ・ライブラリー・マーシャリング:

メソッドおよびプロパティーでオートメーション互換データ型のみを使用する場合、COM は自動的に Universal Marshaller をサーバーのプロキシー/スタブとして使用します。Universal Marshaller はタイプ・ライブラリーにあるサーバーの記述を使用して、引数をマーシャリングする方法を決定します。この方法をタイプ・ライブラリー・マーシャリングと言います。タイプ・ライブラリー・マーシャリングを使用するには、サーバーをオートメーション互換データ型に制限するだけです。

MIDL ベース・マーシャリング:

プロジェクトは、MIDL コンパイラーを使用して、サーバーの IDL 記述をタイプ・ライブラリーにコンパイルします。同時に、MIDL コンパイラーは、サーバーのプロキシー/スタブ DLL をビルドするのに必要な C ソースコードも生成します。MIDL によって生成されたコードからプロキシー/スタブ DLL をビルドするには、C コンパイラーが必要です。プロキシー/スタブ DLL は、それ自身がインプロセス DLL サーバーであり、システムに登録する必要があります。サーバーでオートメーション互換データ型以外を使用し、クライアントが異なる実行コンテキストでサーバーを使用する場合は、MIDL ベース・マーシャリングを使用する必要があります。

カスタム・マーシャリング:

サーバーは IMarshall インターフェイスを実装することで、独自のマーシャリングを実装することができます。この方法は、一般的に多くの作業を必要とし、パフォーマンス上の理由で使用されます。

生成される Do Not Edit コードのマップ

このセクションでは、ウィザードによって Do Not Edit ソースファイルとして生成される COM サーバー機能の概要について説明します。

ファイル名

説明

server.idl

サーバーの IDL 記述。サーバーのタイプ・ライブラリーを生成するために MIDL コンパイラーによりコンパイルされます。

servernameglobal.f90

サーバーのグローバルデータおよび関数。

dllmain.f90

(DLL サーバー)

すべての COM サーバー DLL で必要なエクスポートされた関数。DllMain、DLLRegisterServer、DLLUnregisterServer、DllGetClassObject、および DllCanUnloadNow が含まれます。

exemain.f90

(EXE サーバー)

EXE サーバーのメイン・エントリー・ポイント。コマンドライン引数も処理します。

serverhelper.f90

サーバーのヘルパー関数。

clsfactty.f90

サーバーによって定義されたクラスのインスタンスを作成する IClassFactory インターフェイスの定義。

clsfact.f90

サーバーによって定義されたクラスのインスタンスを作成する IClassFactory インターフェイスのメソッド。

classnameTY.f90

クラスの実装で使用される引数および型の定義を含むモジュールの定義。クラスの IUnknown メソッドの実装も含まれます。サーバーで定義されている各クラスに対して、このファイルの個別のインスタンスが生成されます。

interfacename.f90

インターフェイスのメソッドの Fortran インターフェイスを含むモジュールの定義。クラスの VTBL から直接呼び出され、ユーザーによって実装されたメソッドを呼び出す Fortran ラッパーの実装も含まれます。クラスで定義されている各インターフェイスに対して、このファイルの個別のインスタンスが生成されます。