• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

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

Participant ,
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

799

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 2 Correct answers

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

...

Votes

Translate

Translate
Guide , May 24, 2022 May 24, 2022

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.

Fo

...

Votes

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.

Votes

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
Participant ,
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

Votes

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())"

 

Votes

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

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...

Votes

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
Participant ,
May 22, 2023 May 22, 2023

Copy link to clipboard

Copied

I recently changed the id prefix of my plugin to the one I requested from adobe.
I also required Script ID/Name Registration because I was using e_Speak and p_said.
after this change I get the following warning

startup-alert-message.png

So changing PrefixId of my Plug-In and e_Speak, p_Said I generated this error.

would you know how to fix it.

P.S. I'm using the correct SDK for the correct version of InDesign so that's not the problem

Votes

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 22, 2023 May 22, 2023

Copy link to clipboard

Copied

LATEST

You probably have a build error so that Xcode does not produce the correct resources folders.

Use Xcode >> Product >> Clean Build Folder to purge debris remaining from previous compiles.

Then rebuild the project.

Have a look at either the Xcode issue navigator (the caution triangle in the left sidebar) or better the report navigator (last icon in the left sidebar). In the large report display showing in place of the source, show all messages, then drill down to the resource compile. You can click the top right of each issue to expand the raw tool's output.

Votes

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