Remote Procedure Call (RPC) is a method by which a module uses a service of another module.
When the calling module calls a method of a dynamic object, Integratec seamlessly performs all the steps necessary to invoke the method remotely and returns the result. This includes determining the appropriate service ID as well as marshaling and unmarshaling the method name, parameters and result.
The dynamic object is based on the IDispatch interface type. Languages that support late-bound COM objects can access this interface as if it were a COM object. Other languages can access this interface using its vtable.
Resource calls are an example of Remote Procedure Call.
- Note
- There is no requirement to use Remote Procedure Call. It is an alternative to sending a JSON formatted request to the service that implements the method. Remote Procedure Call takes advantage of the dynamic features of the language. When using the C language, which is strongly typed and therefore poorly suited to dynamic code, you may find it easier to send a JSON formatted request.
C#
call.Say("Hello World!");
Python
1 call.Say(
"Hello World!")
This is for illustrative purposes only. Say
is not an actual method that is implemented.
Request
The request has a method
property, which is the method name (and case insensitive), and a params
property, which is an array of parameters passed to the method.
{
"method" : "Say",
"params" : [
"Hello World!"
]
}
Reply
The reply has a reply
property, which is the return value of the method.
Examples
To make a remote procedure call, first get an IDispatch interface or dynamic object, then call a method of it.
C
#include <windows.h>
#include <stdio.h>
void* call;
return E_FAIL;
IDispatch *dispatch = (IDispatch *)call;
DISPID dispId;
OLECHAR *name = L"resourceGet";
HRESULT hr;
hr = dispatch->lpVtbl->GetIDsOfNames(dispatch, &IID_NULL, &name, 1, LOCALE_SYSTEM_DEFAULT, &dispId);
if (!SUCCEEDED(hr))
return hr;
SAFEARRAYBOUND bound[1];
bound[0].cElements = 1;
bound[0].lLbound = 0;
LONG indexes[1];
indexes[0] = 0;
SAFEARRAY *resourceId = SafeArrayCreate(VT_BSTR, 1, bound);
if (!resourceId)
return E_FAIL;
BSTR str;
str = SysAllocString(L"addressTables");
if (!str)
return E_OUTOFMEMORY;
hr = SafeArrayPutElement(resourceId, &indexes[0], str);
SysFreeString(str);
if (!SUCCEEDED(hr))
return hr;
VARIANT resourceIdVar;
VariantInit(&resourceIdVar);
resourceIdVar.vt = VT_ARRAY | VT_BSTR;
resourceIdVar.parray = resourceId;
DISPPARAMS dispParams;
VARIANTARG args[1];
args[0] = resourceIdVar;
dispParams.cArgs = 1;
dispParams.rgvarg = &args[0];
VARIANT varResult;
hr = dispatch->lpVtbl->Invoke(dispatch, dispId, &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispParams, &varResult, NULL, NULL);
if (varResult.vt == VT_BSTR)
wprintf(varResult.bstrVal);
SafeArrayDestroy(resourceId);
dispatch->lpVtbl->Release(dispatch);
C#
dynamic call = api.call;
string replyJson = call.resourceGet(new string[] { "addressTables" });
Python
2 replyJson = call.resourceGet( [
'addressTables' ] )