Integratec API Platform
Remote Procedure Call

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.

{
"reply" : null
}

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 to get declarations for IDispatch, VARIANT, SUCCEEDED, etc.
#include <windows.h>
// Include stdio.h to get declaration for wprintf()
#include <stdio.h>
// Get IDispatch interface
void* call;
if (!opClientConnectionGetCall(connection, &call, &errorMsg))
return E_FAIL;
IDispatch *dispatch = (IDispatch *)call;
// Get DISPID for resourceGet
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;
// Create resourceId SafeArray for [ "addressTables" ]
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;
// Build DISPPARAMS
DISPPARAMS dispParams;
VARIANTARG args[1];
args[0] = resourceIdVar;
dispParams.cArgs = 1;
dispParams.rgvarg = &args[0];
// Invoke resourceGet
VARIANT varResult;
hr = dispatch->lpVtbl->Invoke(dispatch, dispId, &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispParams, &varResult, NULL, NULL);
// Print result
if (varResult.vt == VT_BSTR)
wprintf(varResult.bstrVal);
// Destroy resourceId SafeArray
SafeArrayDestroy(resourceId);
// Release IDispatch interface
dispatch->lpVtbl->Release(dispatch);

C#

dynamic call = api.call;
string replyJson = call.resourceGet(new string[] { "addressTables" });

Python

1 call = api.call
2 replyJson = call.resourceGet( [ 'addressTables' ] )