RAD Studio
|
To call an invokable interface, your client application must include any definitions of the invokable interfaces and any remotable classes that implement complex types.
If the server is written in Delphi or C++Builder, you can use the same units that the server application uses to define and register these interfaces and classes instead of the files generated by importing a WSDL file. Be sure that the unit uses the same namespace URI and SOAPAction header when it registers invokable interfaces. These values can be explicitly specified in the code that registers the interfaces, or it can be automatically generated. If it is automatically generated, the unit that defines the interfaces must have the same name in both client and server, and both client and server must define the global AppNameSpacePrefix variable to have the same value.
Once you have the definition of the invokable interface, there are two ways you can obtain an instance to call:
The WSDL importer automatically generates a function from which you can obtain the invokable interfaces you imported. For example, if you imported a WSDL document that defined an invokable interface named IServerInterface, the generated unit would include the following global function:
function GetIServerInterface(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO): IServerInterface;
_di_IServerInterface GetIServerInterface(bool UseWSDL, AnsiString Addr, THTTPRIO* HTTPRIO);
The generated function takes three parameters: UseWSDL, Addr, and HTTPRio. UseWSDL indicates whether to look up the location of the server from a WSDL document (true), or whether the client application supplies the URL for the server (false).
When UseWSDL is false, Addr is the URL for the Web Service. When UseWSDL is true, Addr is the URL of a WSDL document that describes the Web Service you are calling. If you supply an empty string, this defaults to the document you imported. This second approach is best if you expect that the URL for the Web Service may change, or that details such as the namespace or SOAP Action header may change. Using this second approach, this information is looked up dynamically at the time your application makes the method call.
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();
If you do not use the global function to obtain the invokable interface you want to call, you can create an instance of THTTPRio for the desired interface:
X := THTTPRio.Create(nil);
X = new THTTPRio(NULL);
If you do not expect the URL for the Web Service or the namespaces and soap Action headers it requires to change, you can simply specify the URL for the Web Service you want to access. THTTPRio uses this URL to look up the definition of the interface, plus any namespace and header information, based on the information in the invocation registry. Specify the URL by setting the URL property to the location of the server:
X.URL := 'http://www.myco.com/MyService.dll/SOAP/IServerInterface';
If you want to look up the URL, namespace, or Soap Action header from the WSDL document dynamically at runtime, you can use the WSDLLocation, Service, and Port properties, and it will extract the necessary information from the WSDL document:
X.WSDLLocation := 'Cryptography.wsdl'; X.Service := 'Cryptography'; X.Port := 'SoapEncodeDecode';
After specifying how to locate the server and identify the interface, you can obtain an interface pointer for the invokable interface from the THTTPRio object. You obtain this interface pointer using the as operator. Simply cast the THTTPRio instance to the invokable interface:
InterfaceVariable := X as IEncodeDecode;
Code := InterfaceVariable.EncodeValue(5);
_di_IEncodeDecode InterfaceVariable;
if (X->QueryInterface(InterfaceVariable) == S_OK)
{
Code = InterfaceVariable->EncodeValue(5);
}
When you obtain the interface pointer, THTTPRio creates a vtable for the associated interface dynamically in memory, enabling you to make interface calls.
THTTPRio relies on the invocation registry to obtain information about the invokable interface. If the client application does not have an invocation registry, or if the invokable interface is not registered, THTTPRio can't build its in-memory vtable.
procedure TForm1.FormDestroy(Sender: TObject); begin InterfaceVariable := nil; end;
void __fastcall TForm1::FormDestroy(TObject *Sender) { InterfaceVariable = NULL; }
The reason you must reassign a global interface variable to nil is because THTTPRio builds its vtable dynamically in memory. That vtable must still be present when the interface is released. If you do not release the interface along with the form or data module, it is released when the global variable is freed on shutdown. The memory for global variables may be freed after the form or data module that contains the THTTPRio object, in which case the vtable will not be available when the interface is released.
Copyright(C) 2008 CodeGear(TM). All Rights Reserved.
|
What do you think about this topic? Send feedback!
|