2

I'm using an embeded IE ActiveX control in my C++ (MFC) application. The embeded IE has a JavaScript method that passes data back to my C++ application using the following (simplified) JavaScript:

function passDataTocpp()

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

}

When I receive it in my C++ code, I get a VARIANT of type VT_DISPATCH. I was able to find this example that converts an array into C++ accessible data but that doesn't seem to work for an associative array (or an object.)

Any idea how to access that data?

Community
  • 1
  • 1
c00000fd
  • 20,994
  • 29
  • 177
  • 400

3 Answers3

3

IDispatch::GetIdsOfNames, IDispatch::Invoke(DISPID_PROPGET). If you don't even know which properties the object has, then query for IDispatchEx and use GetNextDispID to enumerate them.

Since you are using ATL, CComDispatchDriver is a convenient wrapper around IDispatch (but not IDispatchEx - that one you'll have to call directly). For some reason, it's not documented in MSDN. Look up CComPtr<IDispatch> specialization in atlcomcli.h, it's reasonably straightforward. CComDispatchDriver is a typedef for it.

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
1

On C++ side the code might look like this (explained on Igor's answer):

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
Roman R.
  • 68,205
  • 6
  • 94
  • 158
0

Following @IgorTandetnik's advice, I came up with the following method that seems to do the job (it's a pseudo-code though):

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;
}
c00000fd
  • 20,994
  • 29
  • 177
  • 400