Edit in GitHubLog an issue

C++ to UXP Communication

For developers with the intent to utilize the C++ based plugin SDK in conjunction with a UXP based plugin, the C++ SDK now includes a method to communicate with its UXP counterpart. On C++ side, we use the component's plugin name property in the plugin resource to identify plugins, and on UXP side, we use the id field from the manifest.json file.

PIUXPSuite

The PIUXPSuite communicates with UXP plugins using PIActionDescriptors. Use the ActionDescriptor suite as defined in the SDK's PIAction.h whenever using this suite. To start with, grab PIUXPSuite.h and add it to your C++ project.

The signatures in PIUXPSuite.h are as follows:

Copied to your clipboard
1typedef void (*PIUXPMessageNotifier)(PIActionDescriptor descriptor);
2typedef struct PsUXPSuite1
3{
4 SPAPI SPErr (*SendUXPMessage) (SPPluginRef selfRef, const char* uxpPluginId, PIActionDescriptor descriptor);
5 SPAPI SPErr (*AddUXPMessageListener) (SPPluginRef selfRef, PIUXPMessageNotifier notifier);
6 SPAPI SPErr (*RemoveUXPMessageListener) (SPPluginRef selfRef);
7
8} PsUXPSuite1;

CSDK to UXP messaging

PsUXPSuite1.SendUXPMessage can be used to send messages to a UXP plugin given the plugin ID (from manifest.json) and an action descriptor containing the message.

Includes and globals#

First, make sure to include the right files and declare the globals to store the important pointers.

Copied to your clipboard
1// Include these
2#include "PIActions.h" // For PIActionDescriptor
3#include "PIUXPSuite.h" // For messaging
4
5// Your globals
6SPBasicSuite * sSPBasic = NULL; // This is passed to your main function
7SPPluginRef gPlugInRef = NULL; // This is passed to your main function
8PsUXPSuite1* sUxpProcs = NULL; // You acquire this using sSPBasic
9PSActionDescriptorProcs* sDescriptorProcs = NULL; // You acquire this using sSPBasic

Based on Plugin Type...#

Automation Plugins: AutoPluginMain#

For Automation plugins, the entry method is called AutoPluginMain use the code below to extract the plugin reference and the basic suite.

Copied to your clipboard
1DLLExport SPAPI SPErr AutoPluginMain(const char* caller, const char* selector, void* message) {
2
3 SPMessageData* basicMessage = (SPMessageData*) message;
4 sSPBasic = basicMessage->basic;
5 gPlugInRef = basicMessage->self;
6 ...

Filter plugins: PluginMain#

Filter plugins use an entry method called PluginMain, in which you can grab the basic suite and the plugin reference directly.

Copied to your clipboard
1DLLExport MACPASCAL void PluginMain(const int16 selector,
2 FilterRecordPtr filterRecord,
3 intptr_t * data,
4 int16 * result) {
5 sSPBasic = filterRecord->sSPBasic;
6 gPlugInRef = filterRecord->plugInRef;
7 ...

Acquiring the suites#

Next up is acquiring the correct suites to create your messages with ActionDescriptors and sending them to the UXP plugin of your choice.

Copied to your clipboard
1// in your main method
2 sSPBasic->AcquireSuite(kPSUXPSuite,
3 kPSUXPSuiteVersion1,
4 (const void**)&sUxpProcs);
5
6 sSPBasic->AcquireSuite(kPSActionDescriptorSuite,
7 kPSActionDescriptorSuiteVersion,
8 (const void**)&sDescriptorProcs);
9
10 PIActionDescriptor desc;
11 sDescriptorProcs->Make(&desc);
12 sDescriptorProcs->PutString(desc, 'helo', "Hello World!");
13 sDescriptorProcs->PutFloat(desc, 'fltp', 0.952);
14
15 const char* UXP_MANIFEST_ID = "com.your.pluginId";
16 sUxpProcs->SendUXPMessage(gPlugInRef, UXP_MANIFEST_ID, desc);
17}

On your UXP plugin#

Add a messaging listener using the messaging API group. Any descriptors sent from a CSDK plugin to the ID of this plugin will arrive on this callback.

Copied to your clipboard
1let callback = (o) => {
2 console.log("Message from " + o.pluginId + ":" + o.message);
3}
4
5require('photoshop').messaging.addSDKMessagingListener(callback);
6
7...
8// You can remove your listener using this API
9require('photoshop').messaging.removeSDKMessagingListener(callback);

UXP to CSDK messaging

For communication from a UXP plugin to a C plugin, define a listener within your CPlugin, and utilize both AddUXPMessageListener and RemoveUXPMessageListener at the appropriate time.

Listener Callback#

All messages sent to this plugin will be handled in this method

Copied to your clipboard
1void UXPMessageHandler(PIActionDescriptor descriptor) {
2 // do something
3}

Adding listener#

Use the code below where you'd like to start listening to messages.

Copied to your clipboard
sUxpProcs->AddUXPMessageListener(gPlugInRef, UXPMessageHandler);

Removing listener#

Use the code below to stop listening to messages from UXP plugins.

Copied to your clipboard
sUxpProcs->RemoveUXPMessageListener(gPlugInRef);

NOTE: Only one notifier per plugin may be registered.

Sending the message from UXP#

To send messages to the C Plugin, take note of the Component Id as defined in its resouce PiPL. This is the second parameter of the PIComponentProperty.

With this Id, use the messaging group of the photoshop package to send your message across.

Copied to your clipboard
1let messageContent = {
2 status: "ok",
3 filter: 416
4};
5window.require('photoshop').messaging.sendSDKPluginMessage(<YourPluginComponentId>, messageContent);
Copyright © 2021 Adobe. All rights reserved.