起動可能インターフェイスの呼び出し
Web サービスの使い方:インデックス への移動
起動可能インターフェイスを呼び出すには、起動可能インターフェイス、および複合型を実装するリモート可能クラスの定義をクライアント アプリケーションに含める必要があります。
サーバーが Delphi または C++Builder で記述されている場合、WSDL ファイルをインポートして生成されたファイルではなく、サーバー アプリケーションがこれらのインターフェイスとクラスを定義および登録するために使用するユニットと同じユニットを使用できます。起動可能インターフェイスの登録時に、ユニットに同じ名前空間 URI および SOAPAction ヘッダーが使用されていることを確認してください。これらの値は、インターフェイスを登録するコードに明示的に指定するか、自動的に生成することができます。自動生成の場合、インターフェイスを定義するユニットはクライアントとサーバーのいずれも同じ名前とし、クライアントとサーバーの両方でグローバル変数 AppNameSpacePrefix に同じ値を定義してください。
起動可能インターフェイスを定義したら、次の 2 つの方法で呼び出すインスタンスを取得できます。
- WSDL ドキュメントをインポートした場合は、インポータによって自動的にインターフェイスを返すグローバル関数が作成されます。この関数を使って呼び出しを行うことができます。
- リモート インターフェイス化オブジェクトを使用できます。
生成された関数から起動可能インターフェイスを取得する
WSDL インポータによって自動生成された関数から、インポートした起動可能インターフェイスを取得できます。たとえば、IServerInterface という名前の起動可能インターフェイスを定義した WSDL ドキュメントをインポートすると、生成されるユニットには次のグローバル関数が組み込まれます。
function GetIServerInterface(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IServerInterface;
_di_IServerInterface GetIServerInterface(bool UseWSDL, AnsiString Addr, THTTPRIO* HTTPRIO);
生成された関数は、UseWSDL、Addr と HTTPRio の 3 つのパラメータをとります。UseWSDL は、WSDL ドキュメントからサーバーの場所を検索する(True)か、クライアント アプリケーションからサーバーの URL が提供される(False)かを示します。
UseWSDL が False の場合、Addr は、Web サービスの URL です。UseWSDL が True の場合、Addr は、呼び出す Web サービスを記述する WSDL ドキュメントの URL です。空の文字列を指定すると、デフォルトでインポートしたドキュメントが指定されます。Web サービスの URL が変更される可能性があったり、名前空間や SOAP Action ヘッダーなどの詳細情報が変更される可能性がある場合は、2 番目の方法が最適です。この 2 番目の方法を使用すると、アプリケーションがメソッドを呼び出したときに情報が動的に検索されます。
メモ: 実行速度を考えると、WSDL パラメータではなく URL を使用することが最良です。WSDL の場合、SOAP ランタイムは、WSDL パラメータ用に HTTP GET を実行してから Web サービスの処理を呼び出す必要があります。HTTPRio パラメータには、インターフェイスを取得するため使用するリモート可能なインターフェイス オブジェクトを指定します。HTTPRio パラメータに NULL 値を指定する場合、メソッドにより新規 THTTPRio インスタンスが作成されます。イベント処理とオブジェクトのカスタマイズに [オブジェクトインスペクタ] を使用する場合は、THTTPRio インスタンスを指定できます。
メモ: 生成された関数は、内部リモート インターフェイス化オブジェクトを使用して、起動可能インターフェイスを実装します。この関数の使用時に、先の基本リモート インターフェイス化オブジェクトをアクセスする必要がある場合、起動可能インターフェイスから IRIOAccess インターフェイスを取得して、それでリモート インターフェイス化オブジェクトにアクセスできます。
var Interf: IServerInterface; RIOAccess: IRIOAccess; X: THTTPRIO; begin Intrf := GetIServerInterface(True, 'http://MyServices.org/scripts/AppServer.dll/wsdl'); RIOAccess := Intrf as IRIOAccess; X := RIOAccess.RIO as THTTPRIO;
_di_EchoUnboundedSoap service = GetEchoUnboundedSoap(); _di_IRIOAccess rioAccess = service; TSOAPConvertOptions options = rioAccess->GetRIO()->Converter->GetOptions();
リモート インターフェイス化オブジェクトの使用
呼び出す対象の起動可能インターフェイスの取得にグローバル関数を使用しない場合、目的インターフェイスに応じた SoapHTTPClient.THTTPRio のインスタンスを作成してください。
X := THTTPRio.Create(nil);
X = new THTTPRio(NULL);
メモ: 重要なことは、THTTPRio インスタンスを明示的に破棄しないということです。前述のコード行のように Owner を使用せずに作成された場合は、インターフェイスが解放されるときにインスタンスは自動的に解放されます。Owner を使って作成された場合は、THTTPRio インスタンスの解放は Owner が行います。
THTTPRio のインスタンスを取得したら、サーバー インターフェイスの識別とサーバーの場所の特定に必要な情報を提供します。この情報を提供する方法は以下の 2 つです。
Web サービスの URL、名前空間と SOAP Action ヘッダーで必要な変更が予想されない場合は、単にアクセスする Web サービスの URL を指定できます。THTTPRio は、この URL を使ってインターフェイスの定義を参照し、起動レジストリ内の情報に基づいて名前空間とヘッダー情報を参照します。URL を指定するには、URL プロパティをサーバーの位置に設定します。
X.URL := 'http://www.myco.com/MyService.dll/SOAP/IServerInterface';
実行時に動的に WSDL ドキュメントから URL、名前空間、または SOAP Action ヘッダーを参照する場合は、WSDLLocation、Service、および Port プロパティを使用して、WSDL ドキュメントから必要な情報を取り出すことができます。
X.WSDLLocation := 'Cryptography.wsdl'; X.Service := 'Cryptography'; X.Port := 'SoapEncodeDecode';
サーバーを探し出してインターフェイスを識別する方法を指定したら、THTTPRio オブジェクトから起動可能インターフェイスのインターフェイス ポインタを取得できます。このインターフェイス ポインタを取得するには、as 演算子を使用します。次のとおり THTTPRio インスタンスを起動可能インターフェイスにキャストします。
InterfaceVariable := X as IEncodeDecode; Code := InterfaceVariable.EncodeValue(5);
_di_IEncodeDecode InterfaceVariable; if (X->QueryInterface(InterfaceVariable) == S_OK) { Code = InterfaceVariable->EncodeValue(5); }
インスタンス ポインタを取得すると、関連付けられたインターフェイスの vtable が THTTPRio によってメモリ内に動的に作成され、インターフェイス呼び出しができるようになります。
THTTPRio は、起動レジストリに依存して起動可能インターフェイスについての情報を取得します。クライアント アプリケーションが起動レジストリを持たない場合、または起動可能インターフェイスが登録されない場合、THTTPRio はメモリ内の vtable を構築できません。
警告: THTTPRio から取得したインターフェイスをグローバル変数に代入する場合、アプリケーションをシャットダウンする前にその割り当てを nil(NULL)に変更する必要があります。たとえば、前のコード例の InterfaceVariable がスタック変数ではなくグローバル変数である場合、THTTPRio オブジェクトが解放される前にインターフェイスを解放する必要があります。通常、このコードはフォームまたはデータ モジュールの OnDestroy イベント ハンドラに置かれます。
procedure TForm1.FormDestroy(Sender: TObject); begin InterfaceVariable := nil; end;
void __fastcall TForm1::FormDestroy(TObject *Sender) { InterfaceVariable = NULL; }
グローバル インターフェイス変数を nil(NULL)に割り当て変更しなければならない理由は、THTTPRio がメモリ内で動的に vtable を構築するからです。その vtable は、インターフェイスが解放されるときにも存在している必要があります。このインターフェイスをフォームまたはデータ モジュールとともに解放しない場合、シャットダウン時にグローバル変数が解放されるときに解放されます。グローバル変数のメモリは、THTTPRio オブジェクトを含むフォームまたはデータ モジュールの後で解放される可能性があり、その場合、インターフェイスが解放されたときに vtable は使用できなくなります。