从Javascript传递对象到C++

3

我已找到从Javascript传递数组到C++的解决方案,但我有另一个任务:如果我使用带有IDispatch的IWebBrowser2,则从Javascript传递对象到C++(我的意思是我需要通过window.external.method调用带有JavaScript对象参数的C++方法)

var obj = {name: "Petr", group: "Friend"};
window.external.myMethod(obj);

如何访问对象成员“name”,“group”等?

好的,那么,关于给定的问题呢? - vinnitu
现在有人帮助了你,那么重新审视一下你的问题怎么样?;D - karlphillip
我已经做了 :) 在你的留言后立刻处理。 - vinnitu
3个回答

2

您可以通过IDispatch接口及其方法GetIDsOfNamesInvoke访问对象的属性。

根据您对myMethod的定义,您在C++代码中应该将obj作为VARIANTIDispatch *接收。如果是一个VARIANT,则vt应该是VT_DISPACTH,这时您可以安全地引用pdispval

一旦您有了一个IDispatch指针,您就可以使用GetIDsOfNames来获取您感兴趣的属性的DISPID,如下所示:

_bstr_t sPropertyName = L"myProperty";
DISPID dispid = 0;
HRESULT hr = pDispatch->GetIDsOfNames(IID_NULL, &sPropertyName, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
if(SUCCEEDED(hr))
{
    ...

一旦你成功获取到DISPID,你需要根据是否想要获取一个值、设置一个值或调用一个方法来不同地调用Invoke
例如,如果想要获取一个值:
    VARIANT vValue;
    hr = pDispatch->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, 0, &vValue, 0, 0);
    if(SUCCEEDED(hr))
    {
        ...

请查看Invoke的文档,了解调用它时不同排列组合的更多信息。


非常好,只有一个问题 - 我们如何枚举对象的所有成员? - vinnitu
我尝试使用pDispatch->GetTypeInfo => ITypeInfo::GetNames - 但是出了些问题 :( - vinnitu

0
static HRESULT \
IDispatch_VarGet (IDispatch *pRDisp, LPOLESTR Name, VARIANT *pVarRes)
{
    DISPPARAMS DispParams;
    DISPID dispid;
    HRESULT hr;

    if ((hr = IDispatch_GetIDsOfNames (pRDisp, &IID_NULL,
                &Name, 1, LOCALE_SYSTEM_DEFAULT, &dispid)))
        return hr;

    ZeroMemory (&DispParams, sizeof (DispParams));

    hr = IDispatch_Invoke (pRDisp, dispid, &IID_NULL,
            LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET,
            &DispParams, pVarRes, NULL, NULL);

    return hr;
}


static HRESULT \
IDispatch_VarPut (IDispatch *pRDisp, LPOLESTR Name, VARIANT *pVarArg)
{
    DISPPARAMS DispParams;
    DISPID dispid, ndispid;
    HRESULT hr;

    if ((hr = IDispatch_GetIDsOfNames (pRDisp, &IID_NULL,
                &Name, 1, LOCALE_SYSTEM_DEFAULT, &dispid)))
        return hr;

    ndispid = DISPID_PROPERTYPUT;

    DispParams.rgvarg = pVarArg;
    DispParams.rgdispidNamedArgs = &ndispid;
    DispParams.cArgs  = 1;
    DispParams.cNamedArgs = 1;

    hr = IDispatch_Invoke (pRDisp, dispid, &IID_NULL,
            LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT,
            &DispParams, NULL, NULL, NULL);

    return hr;
}


static HRESULT \
IDispatch_StrPut (IDispatch *pRDisp, LPOLESTR Name, LPOLESTR StrVal)
{
    VARIANT varg;
    HRESULT hr;

    VariantInit (&varg);

    V_VT   (&varg) = VT_BSTR;
    V_BSTR (&varg) = SysAllocString (StrVal);

    hr = IDispatch_VarPut (pRDisp, Name, &varg);

    VariantClear (&varg);

    return hr;
}


static HRESULT \
IDispatch_IntPut (IDispatch *pRDisp, LPOLESTR Name, int IntVal)
{
    VARIANT varg;
    HRESULT hr;

    VariantInit (&varg);

    V_VT (&varg) = VT_I4;
    V_I4 (&varg) = IntVal;

    hr = IDispatch_VarPut (pRDisp, Name, &varg);

    VariantClear (&varg);

    return hr;
}

...

if ((hr = IDispatch_StrPut (pRDisp, L"code", buff)))
    return hr;

if ((hr = IDispatch_IntPut (pRDisp, L"state", state)))
    return hr;

...

{
    // ...
    VariantInit (&varg);

    if ((hr = IDispatch_VarGet (pRDisp, L"code", &varg)))
    {
        VariantClear (&varg);
        return hr;
    }

    if (V_VT (&varg) == VT_BSTR)

    // ...

    VariantClear (&varg);
    return hr;
}

以及Java代码示例...

var frec = {code:'', state:0};

frec.code = row.cells[0].innerHTML;
external.FeatureStateChg (frec);
_featState (row.cells[2], frec.state);

...

var frec = {code:'', name:'', state:0};

if (!external.FeaturesEnum (frec, i))
    break;

3
一些解释也会受到欣赏。 - ramaral

0
如果您只需要能够读取对象字段,最灵活的方法是使用JSON。
在您的网页上使用:
var obj = {name: "Petr", group: "Friend"}; window.external.myMethod(JSON.stringify(obj));
在您的C++端定义myMethod()以接受单个字符串参数。然后使用C++ JSON解析器将此参数解析为可读对象。

我知道并正在做,但我认为可以用与上面文章中链接相同的方式实现,但我不是COM方面如此高级的用户 :(( - vinnitu
1
以上文章来自ExpertsExchange。我认为在SO上链接它们不是一个好主意... - Boaz Yaniv
我没有在ExpertsExchange注册。 - vinnitu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接