是否可以将 Javascript 对象传递给 ActiveX(并使用它们)?

发布于 2024-12-09 01:44:50 字数 1881 浏览 0 评论 0原文

我想将 JavaScript 对象(JSON 和函数对象)传递到我的 ActiveX 控件中。理想情况下,我可以操作 JavaScript 对象(例如读取或修改 JSON)并从 ActiveX 控件内执行 JavaScript 函数调用(使用 C++)。这有可能吗,还是我必须满足于传递字符串?

例如,这是我在 Firefox 中可以执行的操作。请注意,我有一个对 JSON 对象的引用,并且我还可以执行 JavaScript 函数调用:

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);
}


编辑 - 这是我提出的解决方案:

IDL 文件:

[id(TEST_ID)] BSTR Test(BSTR data, IDispatch* function);


调度图:

DISP_FUNCTION_ID(CApp, "test", TEST_ID, Test, VT_BSTR, VTS_BSTR VTS_DISPATCH)


接口功能:

BSTR Test(BSTR data, IDispatch* function)


调用 JavaScript 函数对象:

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);

使用 DISPID 0 调用 IDispatch::Invoke 似乎适用于调用函数对象。然而,要调用对象的方法,必须先获取相应的DISPID,正如Taxilian所说。 GetNextDispID 应该适用于此(IDispatchEx 的第一个 QueryInterface;转换为 IDispatchEx 似乎也适用,但可能不安全)。

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

剪不断理还乱 2024-12-16 01:44:50

哇,我今天显然不太聪明,因为我刚刚写了一个答案,完全遗漏了您所说的 npapi 插件代码是示例的部分 =]

所以,要回答正确的问题,是的,您可以。 ActiveX 中与 NPObject 最相关的类型是 IDispatch(或 IDispatchEx)。您只需调用 Invoke 并告诉它是否应该获取属性、设置属性或调用方法,而不需要使用 GetProperty、SetProperty 和 Invoke。您首先必须查询以获取相关成员的 DISPID;与 NPIdentifier 类似,DISPID 是字符串和数字之间的映射。

如果您还没有看过它,您应该真正看看 FireBreath,它提供了一个抽象,允许您编写插件它适用于具有相同代码库的 NPAPI 和 ActiveX。它有一个包装器以允许它使用IDispatch对象您可能会发现它作为示例很有用。

长话短说,您可以像使用 NPObject 一样使用 JS 对象,即使用 IDispatch(或者更好的是 IDispatchEx)。 javascript 中的大多数内容都是作为 IDispatchEx 实现的,但偶尔我也会看到需要 IDispatch 故障转移支持的实例。

希望它有帮助,我希望我最初的回答(在我重新阅读你的问题之前)不会让你失望。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文