I want to pass JavaScript objects (JSON and function objects) into my ActiveX control. Ideally, I could manipulate JavaScript objects (e.g. reading or modifying JSON) and perform JavaScript function calls from within the ActiveX control (using C++). Is any of this possible, or do I have to settle for passing strings?
For example, here is what I can do in Firefox. Notice that I have a reference to a JSON object, and I can also perform JavaScript function calls:
NPString jsonToString(NPP instance, NPObject* json)
{
NPVariant result;
NPVariant arg;
NPIdentifier identifier;
/* Get the global object */
NPObject* windowObj = NULL;
g_NPNFuncs.getvalue(instance, NPNVWindowNPObject, &windowObj);
/* Get JSON object */
identifier = g_NPNFuncs.getstringidentifier("JSON");
g_NPNFuncs.getproperty(instance, windowObj, identifier, &result);
NPObject* jsonObj = NPVARIANT_TO_OBJECT(result);
/* Call stringify */
identifier = g_NPNFuncs.getstringidentifier("stringify");
OBJECT_TO_NPVARIANT(json, arg);
g_NPNFuncs.invoke(instance, jsonObj, identifier, &arg, 1, &result);
return NPVARIANT_TO_STRING(result);
}
Edit - Here's the solution I came up with:
IDL file:
[id(TEST_ID)] BSTR Test(BSTR data, IDispatch* function);
Dispatch map:
DISP_FUNCTION_ID(CApp, "test", TEST_ID, Test, VT_BSTR, VTS_BSTR VTS_DISPATCH)
Interface function:
BSTR Test(BSTR data, IDispatch* function)
Calling the JavaScript function object:
VARIANTARG args[1];
args[0].vt = VT_BSTR;
args[0].bstrVal = _bstr_t(dataStr).GetBSTR();
DISPPARAMS params;
params.cArgs = 1;
params.cNamedArgs = 0;
params.rgvarg = args;
HRESULT hresult = function->Invoke(0, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, NULL, NULL, NULL);
Calling IDispatch::Invoke with a DISPID of 0 seems to work for invoking a function object. However, to call a method of an object, you have to get the corresponding DISPID first, as Taxilian said. GetNextDispID should work for that (first QueryInterface for IDispatchEx; casting to IDispatchEx seems to work too, but maybe isn't safe).