Glue42 Enterprise is now io.Connect Desktop! The new documentation site for all interop.io products is located at docs.interop.io.

Data Sharing Between Apps

Using Shared Contexts

See the Delphi 10 and Delphi 7 examples on GitHub.

In order to use shared contexts, you must implement the IGlueContextHandler interface:

TMainForm = class(TForm, IGlueContextHandler)
...
private
  G42: IGlue42;
  // The shared context handle.
  myContext: IGlueContext;
protected
  function HandleContext(const context: IGlueContext): HResult; stdcall;
  function HandleContextUpdate(const contextUpdate: IGlueContextUpdate): HResult; stdcall;
  ...

Subscribing for Context Updates

To subscribe for context updates, use the SubscribeGlueContext method. If the context doesn't exist, a new empty context will be created:

TMainForm = class(TForm, IGlueContextHandler)
  ...
  procedure TMainForm.InitializeGlue;
    ...
    G42.Start(inst);
    // Subscribe for context updates.
    G42.SubscribeGlueContext('myContextName', Self);
    ...

Handling Context Updates

To handle a newly activated shared context subscription, use the HandleContext method:

function TMainForm.HandleContext(const context: IGlueContext): HResult; stdcall;
begin
  // Store the context handle.
  if context.GetContextInfo.Name = 'myContextName' then
    myContext := context;

  Result := S_OK;
end;

To handle updates of the shared context data, use the HandleContextUpdate method:

function TMainForm.HandleContextUpdate(const contextUpdate: IGlueContextUpdate): HResult; stdcall;
var
  context: IGlueContext;
  contextName: WideString;
  data: TGlueContextValueArray;
begin
  context := contextUpdate.GetContext();
  contextName := context.GetContextInfo.Name;
  // Get the context data in a native data structure.
  rawData := context.GetData();
  data := SA_AsTranslatedContextValues(rawData);
  ...
  SafeArrayDestroy(rawData);
  Result := S_OK;
end;

Updating Contexts

To update the data of a shared context, use the SetContextData method of the IGlueContext interface. The data must be provided as a PSafeArray containing GlueContextValue values:

var
  psaData: PSafeArray;
  nativeData: array[0..0] of TGlueContextValue;
  emails: array of TGlueValue;
begin
  // Initiate an array with data.
  SetLength(emails,2);
  emails[0] := CreateValue('vernon.mullen@acme.com');
  emails[1] := CreateValue('vernon.d.mullen@acme.com');

  // Create the data with native types.
  nativeData[0] := CreateContextValue('contact', CreateComposite([
    CreateContextValue('name', CreateComposite([
      CreateContextValue('firstName', CreateValue('Vernon')),
      CreateContextValue('lastName', CreateValue('Mullen'))
    ], false)),
    CreateContextValue('displayName', CreateValue('Vernon Mullen')),
    CreateContextValue('emails', CreateTuple(emails))
  ], false));

  // Pack the native data into a `PSafeArray`.
  psaData := CreateContextValues_SA(AsGlueContextValueArray(nativeData));

  // Replace the context data.
  context01.SetContextData(psaData);

  // Clean up.
  SafeArrayDestroy(psaData);
end;

The resulting context data from the previous example, represented as JSON:

{
    "contact": {
        "name": {
            "firstName": "Vernon",
            "lastName": "Mullen"
        },
        "displayName": "Vernon Mullen",
        "emails": [
            "vernon.mullen@acme.com",
            "vernon.d.mullen@acme.com"
        ]
    }
}

If you don't want to overwrite the contents of the entire context, you can set a specific elementary or composite value by using the SetContextDataOnFieldPath method:

var
  psaData: PSafeArray;
begin
  // Pack the data into a `PSafeArray`.
  psaData := CreateContextValues_SA(AsGlueContextValueArray([
    CreateContextValue('name', CreateComposite([
      CreateContextValue('firstName', CreateValue('Vernon')),
      CreateContextValue('lastName', CreateValue('Mullen'))
    ], false)),
    CreateContextValue('displayName', CreateValue('Vernon Mullen')),
    CreateContextValue('emails', CreateTuple([
      CreateValue('vernon.mullen@acme.com'),
      CreateValue('vernon.d.mullen@acme.com')
    ]))
  ]));

  // Replace the context value for 'data.contact'.
  context01.SetContextDataOnFieldPath('data.contact', psaData);

  // Clean up.
  SafeArrayDestroy(psaData);
end;

You can also set a specific elementary or composite value by directly providing a JSON string to the UpdateContextDataJson method:

  ...
  // Replace the context value for 'data.contact'.
  context01.SetContextDataOnFieldPath('data.contact','{"name":{"firstName":"Vernon","lastName":"Mullen"}}');
  ...

Listing All Available Contexts

To obtain a list of all available contexts, use the GetKnownContexts method:

var
  saContexts: PSafeArray;
  contexts: array of GlueContext;
begin
  saContexts := G42.GetKnownContexts();
  contexts := SA_AsGlueContextArray(saContexts);
  ...
  SafeArrayDestroy(saContexts);
end;