Как преобразовать объект JavaScript для доступа к его данным из C++?

Я использую встроенный элемент управления IE ActiveX в моем приложении C++ (MFC). Встроенный IE имеет метод JavaScript, который передает данные обратно в мое приложение C++, используя следующий (упрощенный) JavaScript:

function passDataTocpp()

{   
    return {key1: 134, key2:'value2'};

}

Когда я получаю его в своем коде C++, я получаю VARIANT типа VT_DISPATCH. Мне удалось найти этот пример, который преобразует массив в доступные для C++ данные, но, похоже, не работает для ассоциативного массива (или объекта).

Есть идеи, как получить доступ к этим данным?

3 ответа

IDispatch::GetIdsOfNames, IDispatch::Invoke(DISPID_PROPGET), Если вы даже не знаете, какими свойствами обладает объект, запросите IDispatchEx и использовать GetNextDispID перечислять их.

Поскольку вы используете ATL, CComDispatchDriver удобная обертка вокруг IDispatch (но нет IDispatchEx - тот, который вам придется позвонить напрямую). По некоторым причинам, это не задокументировано в MSDN. Уважать CComPtr<IDispatch> специализация в atlcomcli.h, это достаточно просто. CComDispatchDriver это typedef для него.

На стороне C++ код может выглядеть так (объяснил ответ Игоря):

STDMETHOD(Foo)(VARIANT vValue)
{
    ATLASSERT(vValue.vt == VT_DISPATCH);
    CComPtr<IDispatch>& pValue = reinterpret_cast<CComPtr<IDispatch>&>
        (vValue.pdispVal);
    CComVariant vItemValue;
    const HRESULT nResult = pValue.GetPropertyByName(L"key1", &vItemValue);
    // vItemValue is VT_I4 134 here

Следуя совету @IgorTandetnik, я пришел к следующему методу, который, кажется, выполняет эту работу (хотя это псевдокод):

BOOL VariantToObjectProperties(CComVariant& var)
{
    HRESULT hr;

    if (var.vt != VT_DISPATCH)
        return FALSE;

    CComPtr<IDispatch> pDispatch = var.pdispVal;

    CComQIPtr<IDispatchEx> pDispatchEx;
    if(FAILED(hr = pDispatch->QueryInterface(IID_IDispatchEx, (void **)&pDispatchEx)))
        return FALSE;

    BSTR bstrName;
    DISPID dispid;

    //Assume success
    BOOL bRes = TRUE;

    //Enumerate object names
    hr = pDispatchEx->GetNextDispID(fdexEnumAll, DISPID_STARTENUM, &dispid);
    while (hr == NOERROR)
    {
        if(SUCCEEDED(hr = pDispatchEx->GetMemberName(dispid, &bstrName)))
        {
            // get DISPID of item
            DISPID dispidIndex = 0;
            LPOLESTR pIndex = reinterpret_cast<LPOLESTR>(const_cast<WCHAR *>(bstrName));
            if(SUCCEEDED(hr = pDispatch->GetIDsOfNames(IID_NULL, &pIndex, 1, LOCALE_USER_DEFAULT, &dispidIndex)))
            {
                CComVariant varItem;
                DISPPARAMS dispParams = {0};
                if(SUCCEEDED(hr = pDispatch->Invoke(dispidIndex, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispParams, &varItem, NULL, NULL)))
                {
                    //Object's property name is in 'bstrName'
                    //Object's property value is in 'varItem'
                }
                else
                {
                    ASSERT(NULL);
                    bRes = FALSE;
                }
            }
            else
            {
                ASSERT(NULL);
                bRes = FALSE;
            }
        }

        SysFreeString(bstrName);
        hr = pDispatchEx->GetNextDispID(fdexEnumAll, dispid, &dispid);
    }

    return bRes && hr == S_FALSE;
}
Другие вопросы по тегам