2014-05-02 1 views
1

J'utilise un contrôle IE ActiveX incorporé dans mon application C++ (MFC). Le embeded IE a une méthode JavaScript qui transmet les données de retour à mon application C++ en utilisant le JavaScript (simplifié) suivant:Comment convertir un objet JavaScript pour accéder à ses données à partir de C++?

function passDataTocpp() 

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

} 

Quand je reçois dans mon code C++, je reçois un VARIANT de type VT_DISPATCH. J'ai été en mesure de trouver this example qui convertit un tableau en données accessibles en C++ mais cela ne semble pas fonctionner pour un tableau associatif (ou un objet.)

Une idée pour accéder à ces données?

Répondre

3

IDispatch::GetIdsOfNames, IDispatch::Invoke(DISPID_PROPGET). Si vous ne savez même pas quelles sont les propriétés de l'objet, recherchez IDispatchEx et utilisez GetNextDispID pour les énumérer.

Puisque vous utilisez ATL, CComDispatchDriver est un wrapper pratique autour de IDispatch (mais pas IDispatchEx - que vous devrez appeler directement). Pour une raison quelconque, il n'est pas documenté dans MSDN. Rechercher CComPtr<IDispatch> spécialisation dans atlcomcli.h, il est raisonnablement simple. CComDispatchDriver est un typedef pour cela.

1

Du côté de C le code pourrait ressembler à ceci (expliqué sur la réponse Igor):

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 
0

Après @ conseils de IgorTandetnik, je suis venu avec la méthode suivante qui semble faire le travail (c'est un pseudo- Code bien):

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; 
} 
Questions connexes