How to pass Object from C++ to JavaScript and vice-versa(Hybrid Plug-In)

New Here ,
May 20, 2022 May 20, 2022

Copy link to clipboard

Copied

Hi Everyone, 

I've the problem of passing data from C++ to JavaScript, when I have to pass string or integers it is not a problem because I use :

For C++

- Utils<IScriptArgs>()->Set()

- Utils<IScriptArgs>()->Get()

For JavaScript

- app.scriptArgs.getValue()

- app.scriptArgs.setValue()

I wanted to know if is possible pass an object of C++ (like IDocument, IMasterPage, IIDXMLElement and other).

I saw classes like ScriptData, IRequestData that can be useful for me, but i've no idea of how use that, i've use that for passing a string from Js to C++, but nothing else.

If someone did something similar, can show me the code to do that?

I thank in advance whoever will answer the question.

- Stefano

TOPICS
How to , SDK

Views

142

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Guide , May 20, 2022 May 20, 2022

Plug-Ins can extend the InDesign DOM with own objects, collections or added properties and methods for existing objects. There are plenty examples, most show how to add a preferences singleton object.

Search the SDK for "ScriptProvider" as that's the interface and service you'd have to implement. The ScriptProvider will also have an associated ScriptInfo resource, that ends up as addition to the JavaScript OMV (object model viewer) file. I'd look at those to decide on the first sample project to

...

Likes

Translate

Translate
Guide ,
May 20, 2022 May 20, 2022

Copy link to clipboard

Copied

Plug-Ins can extend the InDesign DOM with own objects, collections or added properties and methods for existing objects. There are plenty examples, most show how to add a preferences singleton object.

Search the SDK for "ScriptProvider" as that's the interface and service you'd have to implement. The ScriptProvider will also have an associated ScriptInfo resource, that ends up as addition to the JavaScript OMV (object model viewer) file. I'd look at those to decide on the first sample project to get started.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
May 23, 2022 May 23, 2022

Copy link to clipboard

Copied

Hi Dirk,

Thank you for your answer, can you link some example of how can i do that, because I've been trying for a long time, but I never understand how it works, nowadays I've only see a simple example in the SDK :

 

Javascript

 

var said = "hello";
    app.speak(said);
    var yourresponse = app.response;
    app.speak(yourresponse);

 

C++

ProjectNameScriptProvider.cpp

 

ErrorCode SCScriptProvider::HandleMethod(ScriptID methodID, IScriptRequestData* data, IScript* parent)
{
	ErrorCode status = kFailure;

	switch (methodID.Get())
	{
	case e_Speak:
		status = Speak(data, parent);
		break;

	default:
		status = CScriptProvider::HandleMethod(methodID, data, parent);
	}

    return status;
}

/* AccessProperty
*/
ErrorCode SCScriptProvider::AccessProperty(ScriptID propID, IScriptRequestData* data, IScript* parent)
{
	ErrorCode status = kFailure;

	switch (propID.Get())
	{
	case p_Response:
		status = AccessResponse(propID, data, parent);
		break;

    default:
		status = CScriptProvider::AccessProperty(propID, data, parent);
    }

    return status;
}

/* Speak
*/
ErrorCode SCScriptProvider::Speak(IScriptRequestData* data, IScript* parent)
{
	ErrorCode status = kFailure;

	ScriptData scriptData;
	status = data->ExtractRequestData(p_Said, scriptData);
	if (status == kSuccess)
	{
		PMString said;
		status = scriptData.GetPMString(said);
		said.SetTranslatable(kFalse);
		CAlert::InformationAlert(said);
	}

	return status;
}

/* AccessResponse
*/
ErrorCode SCScriptProvider::AccessResponse(ScriptID propID, IScriptRequestData* data, IScript* parent)
{
	ErrorCode status = kFailure;
	if (data->IsPropertyGet())
	{
		ScriptData scriptData;
		scriptData.SetWideString(WideString("Hello from CPP!"));
		data->AppendReturnData( parent, propID, scriptData ) ;
		status = kSuccess;
	}

	return status;
}

 

ProjectName.fr

 

resource VersionedScriptElementInfo(2)
{
	// Contexts
	{
        kFiredrakeScriptVersion, kCoreScriptManagerBoss, kInDesignAllLanguagesFS, k_Wild,
		kFiredrakeScriptVersion, kCoreScriptManagerBoss, kInCopyAllLanguagesFS, k_Wild,
	}
	
	// Elements
	{
		// Specifies a scripting API method called 'speak' 
		Method
		{
			kSCMethodScriptElement,
			e_Speak,
			"speak",
			"Displays what you say in dialog",
			VoidType,
			{
				p_Said, "said", "Holds a string", StringType, kRequired,
			}
		}

		// Specifies a property called 'response'
		Property
		{
			kSCPropertyScriptElement,
			p_Response,
			"response",
			"Describes user response to dialog",
			StringType,
			{}
			kNoAttributeClass,
		}
		
		// Connects this plug-in's methods and properties to scripting.
		Provider
		{
			kSCScriptProviderBoss,	// provider boss ID
			{
				Object{ kApplicationObjectScriptElement },
				Method{ kSCMethodScriptElement },
				Property{ kSCPropertyScriptElement, kReadOnly },
			}
		}
	}
};

 

I think this is the way to pass objects between C++ and javascirpt, but I don't understand how exactly it works, if I had to pass other objects than a simple PMString I would not know how to do it, for example if I wanted to pass an XML object, an image or a page how i should do?

- Stefano

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
May 24, 2022 May 24, 2022

Copy link to clipboard

Copied

Drop the SDK folder on BBEdit file search, restrict to cpp extension, and search for ScriptProvider. This should give you about 650 hits in 32 files.

 

Your choice above is a single method e_Speak. Let's stick with that. In the argument list the single argument p_Said is declared as StringType so it will accept a string and convert other arguments to fit by using toString() or similar. If you change that to ObjectType(kYourTypeObjectScriptElement), the method would accept an object of that type.

For example, in SnipRun.fr the argument p_SnipRunSnippetToCheck is VariableType { StringType, ObjectType(kSnpRunnableObjectScriptElement) } so it can be either a string or object. You have to figure out the OSE (ObjectScriptElement) constant for the correct preexisting type (they reside in *ID.h files and end in ObjectScriptElement). For example, there is a kPageItemObjectScriptElement .

Regarding XML - you can't pass ExtendScript XML as object, it will get converted to string. You can pass kXMLElementObjectScriptElement from InDesign's document XML.

In the receiving side, you pick up the argument with "ExtractRequestData(p_Said,..." and have a ScriptData - roughly the equivalent to a var. A slot that can be anything. Ask it for the type and use the appropriate getter method. E.g. follow SnipRunScriptProvider::HandleEvent_IsSnippetRegistered, following "switch (scriptData.GetType())"

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
May 24, 2022 May 24, 2022

Copy link to clipboard

Copied

LATEST

Remember to allocate plug-in IDs and script IDs used by your plug-in before your plug-in is published. In your example, that would be the value for "e_Speak" and the associated name "speak" (you'd have to suggest different ones), but also the prefix used for kSCMethodScriptElement.

 

I think the process has not changed since 2018, it involves an email as described here:

https://community.adobe.com/t5/indesign-discussions/prefix-id-registration-web-page-missing/m-p/8883...

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines