开发者

Is it possible to pass Javascript objects to ActiveX (and use them)?

开发者 https://www.devze.com 2023-04-12 07:18 出处:网络
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 c

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 J开发者_高级运维avaScript 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, &params, 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).


Wow, I'm aparently not very bright today because I just wrote up an answer completely missing the part where you said the npapi plugin code was an example =]

so, to answer the correct question, yes you can. The type in ActiveX that closest correlates to NPObject is IDispatch (or IDispatchEx). Rather than having a GetProperty, SetProperty, and Invoke, you merely call Invoke and tell it if it should get a property, set a property, or invoke a method. You'll first have to query to get the DISPID of the member in question; similar to a NPIdentifier, DISPID is a mapping between a string and a number.

If you haven't seen it you should really look at FireBreath, which provides an abstraction to allow you to write a plugin that works on both NPAPI and ActiveX with the same codebase. It has a wrapper to allow it to use IDispatch objects that you'll probably find useful as an example.

So long story short, you can use JS objects pretty much the same way you could with a NPObject by using IDispatch (or even better, IDispatchEx). Most things from javascript come through as a IDispatchEx, but occasionally I've seen instances where IDispatch failover support was needed.

Hope it helps, and I hope my initial response (before I re-read your question) didn't throw you off.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号