如何转换 JavaScript 对象以从 C++ 访问其数据?

Posted

技术标签:

【中文标题】如何转换 JavaScript 对象以从 C++ 访问其数据?【英文标题】:How to convert a JavaScript object to access its data from C++? 【发布时间】:2014-06-19 15:29:27 【问题描述】:

我在我的 C++ (MFC) 应用程序中使用嵌入式 IE ActiveX 控件。嵌入的 IE 有一个 javascript 方法,它使用以下(简化的)JavaScript 将数据传回我的 C++ 应用程序:

function passDataTocpp()

   
    return key1: 134, key2:'value2';


当我在我的 C++ 代码中收到它时,我得到一个 VT_DISPATCH 类型的 VARIANT。我能够找到 this example 将数组转换为 C++ 可访问数据,但这似乎不适用于关联数组(或对象)。

知道如何访问这些数据吗?

【问题讨论】:

【参考方案1】:

IDispatch::GetIdsOfNamesIDispatch::Invoke(DISPID_PROPGET)。如果您甚至不知道该对象具有哪些属性,请查询 IDispatchEx 并使用 GetNextDispID 枚举它们。

由于您使用的是 ATL,CComDispatchDriverIDispatch 的便捷包装器(但不是 IDispatchEx - 您必须直接调用该包装器)。出于某种原因,它没有记录在 MSDN 中。在 atlcomcli.h 中查找 CComPtr<IDispatch> 专业化,它相当简单。 CComDispatchDriver 是它的 typedef。

【讨论】:

【参考方案2】:

在 C++ 方面,代码可能如下所示(在 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

【讨论】:

【参考方案3】:

按照@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;

【讨论】:

以上是关于如何转换 JavaScript 对象以从 C++ 访问其数据?的主要内容,如果未能解决你的问题,请参考以下文章

QML/QT 如何将对象从 C++ 转换为 QML?

如何附加调试器以从托管(C#)包装器进入本机(C++)代码?

将 QJsonObject 转换为 Javascript 对象

如何将 AsyncTask 转换为 Retrofit 以从 Android 中的 WCF Webservice 获取数据

如何将 C++ 对象转换为 PyObject?

如何使用 Emscripten 将对象从 Javascript 传递到 C++