起動可能インターフェイスについて
Web サービスの利用:インデックス への移動
Web サービスをサポートするサーバーは,起動可能インターフェースを使って構築されます。起動可能インターフェースとは,実行時型情報(RTTI:Runtime Type Information)を含むようにコンパイルされるインターフェースです。サーバーでは,この RTTI は,クライアントから受信したメソッド呼び出しを正しくマーシャリングできるように解釈するときに使用されます。クライアントでは,この RTTI は,インターフェースのメソッドを呼び出すためのメソッドテーブルを動的に生成するために使用されます。
起動可能インターフェースを作成するには,{$M+} コンパイラオプションを使ってインターフェースをコンパイルするだけで済みます。起動可能インターフェースの下位も起動可能です。ただし,起動可能でない別のインターフェースを起動可能インターフェースが継承する場合,Web サービスは,起動可能インターフェースとその下位で定義されたメソッドしか使用することができません。起動可能でない上位を継承するメソッドは,型情報を使ってコンパイルされないので,Web サービスの一部として使用することができません。
Web サービスの定義では,基本の起動可能インターフェースである System.IInvokable から,起動可能インターフェースを派生することができます。IInvokable は,System ユニットに定義されています。IInvokable が{$M+} コンパイラスイッチを使ってコンパイルされている点を除けば,IInvokable と IInterface はまったく同じです。{$M+} コンパイラオプションを使用することで,インターフェースとそのすべての下位が RTTI を含むようにコンパイルされます。
たとえば,次のコードは,数値のエンコードとデコードを行う 2 つのメソッドを含む起動可能インターフェースを定義しています。
IEncodeDecode = interface(IInvokable)
['{C527B88F-3F8E-1134-80e0-01A04F57B270}']
function EncodeValue(Value: Integer): Double; stdcall;
function DecodeValue(Value: Double): Integer; stdcall;
end;
__interface INTERFACE_UUID("{C527B88F-3F8E-1134-80e0-01A04F57B270}") IEncodeDecode :
public IInvokable
{
public:
virtual double __stdcall EncodeValue(int Value) = 0 ;
virtual int __stdcall DecodeValue(double Value) = 0 ;
};
メモ: 起動可能インターフェースでは,オーバーロードメソッドを使用できますが,パラメータカウントで異なるオーバーロードを区別できる場合に限られます。つまり,デフォルトのパラメータを考慮に入れた場合を含め,パラメータの数が同じオーバーロードが複数あってはなりません。
Web サービスアプリケーションがこの起動可能インターフェースを使用できるようにするには,その前にインターフェースを起動レジストリに登録しなければなりません。サーバーでは,起動レジストリのエントリを使用すると,インボーカコンポーネント(SOAPHTTPPasInv.THTTPSOAPPascalInvoker)が,インターフェース呼び出しの実行に使用する実装クラスを識別することができます。クライアントアプリケーションでは,起動レジストリのエントリを使用すると,起動可能インターフェースを識別する情報をリモートインターフェース化オブジェクト(SoapHTTPClient.THTTPRio)が検索でき,その呼び出し方法についての情報が提供されます。
通常は,Web サービスのクライアントまたはサーバーは,WSDL ドキュメントをインポートするか Web サービスウィザードを使用して,起動可能インターフェースを定義するコードを作成します。デフォルトでは,WSDL インポータまたは Web サービスウィザードがインターフェースを生成するときに,Web サービスと同名のユニットに定義が追加されます。このユニットには,インターフェース定義と起動レジストリにインターフェースを登録するためのコードが含まれています。起動レジストリは,登録されたすべての起動可能インターフェース,その実装クラス,および実装クラスのインスタンスを作成する関数のカタログです。起動レジストリは,グローバル関数 InvRegistry でアクセスします。この関数は InvokeRegistry ユニットに定義します。
起動可能インターフェースの定義はユニットの interface 部に,インターフェースを登録するコードは初期化部に追加されます。登録コードは次のようになります。
initialization
InvRegistry.RegisterInterface(TypeInfo(IEncodeDecode));
end.
static void RegTypes()
{
InvRegistry()->RegisterInterface(__delphirtti(IEncodeDecode), "", "");
}
#pragma startup RegTypes 32
メモ: implementation 部の uses 節には,InvRegistry 関数が定義されるように InvokeRegistry ユニットを含める必要があります。
Web サービスのインターフェースは,すべての可能な Web サービスの中のすべてのインターフェースからそのインターフェースを識別する名前空間を持たなければなりません。上の例では,インターフェースの名前空間が提供されていません。明示的に名前空間が提供されない場合は,起動レジストリによって自動的に生成されます。この名前空間は,アプリケーションをユニークに識別する文字列(AppNamespacePrefix 変数),インターフェース名,およびインターフェースを定義するユニットの名前から構築されます。自動生成された名前空間を使用したくない場合は,RegisterInterface 呼び出しの 2 番めのパラメータを使って明示的に名前空間を指定できます。
クライアントとサーバーの両方のアプリケーションで同じユニットファイルを使って起動可能インターフェースを定義できます。この場合,起動可能インターフェースを定義するユニットは,そのインターフェースを実装するクラスを記述するユニットとは分けたほうがよいでしょう。生成される名前空間には,インターフェースが定義されるユニットの名前が含まれるため,クライアントアプリケーションとサーバーアプリケーションで同じユニットを共有すると,AppNamespacePrefix 変数に同じ値を使用する限り,同じ名前を自動的に使用できます。
前の例では,インターフェースのメソッドでスカラー型(整数と倍精度浮動小数点)だけを使用しています。非スカラー型も使用できますが,それには少し別の作業が必要になります。