![]() |
![]() |
![]() |
![]() |
![]() |
サーバー側のマッピングとは、C++で記述されたオブジェクト実装の移植性に関する制約のことです。サーバーという用語は、アドレス空間またはマシン境界を越えてメソッドが呼び出されるという状況に実装を制限するものではありません。ここでのマッピングは、Object Management Group (OMG)インタフェース定義言語(IDL)のインタフェースのあらゆる実装にアドレス指定します。
注意: この章の情報は、Object Management Group (OMG)の『Common Object Request Broker: Architecture and Specification, Revision 2.4.2』(2001年2月)に基づいています。OMGの許可を得て使用されています。継承ベースのインタフェース実装の手法では、実装クラスは、OMG IDLインタフェース定義に基づいて生成されたベース・クラスから派生します。生成されたベース・クラスはスケルトン・クラスと呼ばれ、派生クラスは実装クラスと呼ばれます。インタフェースの各操作には、スケルトン・クラスで宣言された対応するメンバー関数があります。生成されたスケルトン・クラスは、インタフェースの各操作に対応するメンバー関数を備えていますが、プログラマにとってはオペークな部分もあります。メンバー関数のシグネチャは、生成されたクライアント・スタブ・クラスのシグネチャと同じです。このインタフェースを継承で実装するには、プログラマはこのスケルトン・クラスから派生させて、OMG IDLインタフェースで操作ごとに実装する必要があります。他の基本インタフェース用のスケルトン・クラスと実装クラスから、エラーやあいまいさをなくして複数のインタフェースに移植性のある実装を可能にするには、スケルトンの仮想ベース・クラスにTobj_ServantBaseクラスを、Tobj_ServantBaseクラスの仮想ベース・クラスにPortableServer::ServantBaseを使用する必要があります。実装クラス、スケルトン・クラス、Tobj_ServantBaseクラス、およびPortableServer::ServantBaseクラスの継承は、すべてパブリック仮想でなければなりません。実装クラスまたはサーバントは、生成した単一のスケルトン・クラスからのみ直接派生する必要があります。複数のスケルトンから直接派生すると、_this()操作の定義が複数あるため、あいまいエラーが発生します。ただし、CORBAオブジェクトには単一の最終派生インタフェースのみがあるので、これは制限ではありません。C++サーバントが複数のインタフェース型をサポートしている場合、デレゲーション・ベースのインタフェース実装の手法に利用できます。リスト15-1に、インタフェース継承を使用したOMG IDLの例を示します。リスト15-1 インタフェース継承を使用したOMG IDLリスト15-2 インタフェース・クラスAポータブル・オブジェクト・アダプタ(POA)の場合、スケルトン・クラスの名前は、対応するインタフェースの完全にスコープ指定された名前の先頭に文字列「POA_」が付きます。また、このクラスは、サーバントのベース・クラスTobj_ServantBaseから直接派生します。次に、Tobj_ServantBaseのC++マッピングを示します。activate_object()およびdeactivate_object()メンバー関数の詳細は、「Tobj_ServantBase:: activate_object()」および「Tobj_ServantBase::_add_ref()」という項を参照してください。リスト15-3に、上で示したインタフェースAのスケルトン・クラスを示します。リスト15-3 インタフェースAのスケルトン・クラスグローバル・スコープ(Mod::Aなど)ではなく、モジュール内部でインタフェースAが定義された場合、そのスケルトン・クラス名はPOA_Mod::Aになります。これは、サーバー・アプリケーションのスケルトンの宣言および定義と、クライアントから生成されたC++コードとを区別するのに役立ちます。このインタフェースを継承で実装するには、このスケルトン・クラスから派生させて、対応するOMG IDLインタフェースで操作ごとに実装する必要があります。インタフェースAの実装クラス宣言は、リスト15-4に示した形式を取ります。リスト15-4 インタフェースAの実装クラスの宣言デレゲーション・ベースの手法では、実装はスケルトン・クラスから継承しません。かわりに、アプリケーションでの必要に応じて実装をコーディングでき、ラッパー・オブジェクトがその実装にアップコールを委任します。このラッパー・オブジェクトは、tieと呼ばれます。IDLコンパイラによって生成され、継承ベースの手法の場合と同じスケルトン・クラスが使用されます。生成されたtieクラスは、スケルトンと同様に、関連付けられたインタフェースの各OMG IDL操作に対応するメソッドを備えていますが、プログラマにとっては非透過的な部分もあります。生成されたtieクラスの名前は、生成されたスケルトン・クラスと同様に、クラス名の末尾に文字列_tieが付け加えられます。tieクラスのインスタンスはサーバントで、tieオブジェクトによって委任されるC++オブジェクトではありません。このサーバントは、Servant引数を必要とする操作に引数として渡されます。また、関連付けられたオブジェクトは、_this( )操作にアクセスしたり、直接データ・メンバーにアクセスしたりすることはできません。型保障tieクラスは、C++テンプレートを使用して実装します。リスト15-5のコードに、前に例示したOMG IDLのDerivedインタフェースから生成されたtieクラスを示します。リスト15-5 Derivedインタフェースから生成されたtieクラス例を見るとわかるように、tieクラスにはインタフェースのop1操作およびop2操作の定義が含まれており、それらの定義ではレガシー・クラスに含まれる操作のシグネチャはIDLでのものと同じであると想定しています。この場合、tieクラス・ファイルをそのまま使用できるため、正確に委任できます。ただし、レガシー・クラスのシグネチャが同じものでなくなるか、単一の関数呼出しよりも作業量が増える可能性が高くなります。その場合、この生成したコード内にあるop1およびop2のコードを自分で置き換える必要があります。各操作のコードは通常、tieクラス変数_ptrを使用してレガシー・クラスへの呼出しを行います。この変数には、レガシー・クラスへのポインタが含まれています。たとえば、次のように行を変更するとします。このテンプレート・クラスのインスタンスは、デレゲーションのタスクを実行します。Derivedインタフェースの操作を提供するクラス型でテンプレートがインスタンス化された場合、POA_Derived_tieクラスは、その実装クラスのインスタンスに操作をすべて委任します。実際の実装オブジェクトに対するリファレンスまたはポインタは、POA_Derived_tieクラスが作成されるときに適切なtieコンストラクタに渡されます。そこでリクエストが呼び出されると、tieサーバントは実装クラスの対応するメソッドを呼び出してリクエストを委任します。実装メンバー関数のシグネチャは、OMG IDL操作のマップされたシグネチャです。クライアント側のマッピングとは異なり、OMGの仕様では、サーバー側のマッピングの関数ヘッダーには適切な例外指定が含まれています。リスト15-6に、この例を示します。リスト15-6 例外の指定すべての操作および属性が原因でCORBAシステム例外は発生するため、操作にraises句がない場合でも、すべての例外指定でCORBA::SystemExceptionを含める必要があります。メンバー関数内で、このポインタはクラスの定義に従って実装オブジェクトのデータを参照します。データへのアクセスに加えて、メンバー関数は同じクラスに定義されている別のメンバー関数を暗黙的に呼び出す場合があります。リスト15-7に、この例を示します。リスト15-7 他のメンバー関数の呼出し