• IE的Trident引擎下实现C++和Javascript相互调用


    我们知道实现C++和Javascript通讯有下表5种接口:

    引擎 编写语言 API接口 C、C++与JavaScript交互(变量、函数、类) vc2005编译静态库的大小 示例EXE的大小 执行、解析JavaScript的速度
    Google V8 C++ C++ 可以 23.1M 1.1M 最快
    Firefox3.5以前 SpiderMonkey C C 可以 1.3M 500K
    Firefox高版本SpiderMonkey C++ C 可以 15.3M 1.7M 一般
    Webkit  JavaScriptCore C++ C 可以 26.2M 1.4M 一般
    IE 未知 COM 可以 未知 100K(没有链接库) 一般

    IE的Trident引擎是非开源的,微软JavaScript引擎也是非开源的。微软对外提供了一组COM接口。使用这组COM接口,能够将微软的JavaScript、VBScript嵌入到C、C++、VB、C#等宿主语言中。

     说到底其实也没什么好说的,先定义一个 CComPtr<IDispatch> 对象,然后调用其对象的Invoke函数,只要弄清楚他的参数正确的传递就好了。

    除此之外该接口还提供有一种简易的方法。

    CComPtr<IDispatch> Obj;
    CComVariant var(true);
    if( FAILED(Obj.Invoke1(L"ReflowDocument", &var)) )
       MessageBox(_T("Invoke ReflowDocument failed."));

    另外还有Invoke0、Invoke2、InvokeN、GetProperty、PutProperty、GetIDOfName、GetPropertyByName。这些函数的实现都在VCatlmfcincludeatlcomcli.h头文件中有声明和实现。

    //specialization for IDispatch
    template <>
    class CComPtr<IDispatch> : 
        public CComPtrBase<IDispatch>
    {
    public:
        CComPtr() throw()
        {
        }
        CComPtr(_Inout_opt_ IDispatch* lp) throw() :
            CComPtrBase<IDispatch>(lp)
        {
        }
        CComPtr(_Inout_ const CComPtr<IDispatch>& lp) throw() :
            CComPtrBase<IDispatch>(lp.p)
        {
        }        
        IDispatch* operator=(_Inout_opt_ IDispatch* lp) throw()
        {
            if(*this!=lp)
            {
                return static_cast<IDispatch*>(AtlComPtrAssign((IUnknown**)&p, lp));
            }
            return *this;
        }
        IDispatch* operator=(_Inout_ const CComPtr<IDispatch>& lp) throw()
        {
            if(*this!=lp)
            {
                return static_cast<IDispatch*>(AtlComPtrAssign((IUnknown**)&p, lp.p));
            }
            return *this;
        }    
        CComPtr(_Inout_ CComPtr<IDispatch>&& lp) throw() :    
            CComPtrBase<IDispatch>()
        {        
            p = lp.p;        
            lp.p = NULL;
        }
        IDispatch* operator=(_Inout_ CComPtr<IDispatch>&& lp) throw()
        {        
            if (*this != lp)
            {
                if (p != NULL)            
                    p->Release();
                
                p = lp.p;
                lp.p = NULL;
            }        
            return *this;
        }    
    // IDispatch specific stuff
        _Check_return_ HRESULT GetPropertyByName(
            _In_z_ LPCOLESTR lpsz, 
            _Out_ VARIANT* pVar) throw()
        {
            ATLASSERT(p);
            ATLASSERT(pVar);
            DISPID dwDispID;
            HRESULT hr = GetIDOfName(lpsz, &dwDispID);
            if (SUCCEEDED(hr))
                hr = GetProperty(dwDispID, pVar);
            return hr;
        }
        _Check_return_ HRESULT GetProperty(
            _In_ DISPID dwDispID, 
            _Out_ VARIANT* pVar) throw()
        {
            return GetProperty(p, dwDispID, pVar);
        }
        _Check_return_ HRESULT PutPropertyByName(
            _In_z_ LPCOLESTR lpsz, 
            _In_ VARIANT* pVar) throw()
        {
            ATLASSERT(p);
            ATLASSERT(pVar);
            DISPID dwDispID;
            HRESULT hr = GetIDOfName(lpsz, &dwDispID);
            if (SUCCEEDED(hr))
                hr = PutProperty(dwDispID, pVar);
            return hr;
        }
        _Check_return_ HRESULT PutProperty(
            _In_ DISPID dwDispID, 
            _In_ VARIANT* pVar) throw()
        {
            return PutProperty(p, dwDispID, pVar);
        }
        _Check_return_ HRESULT GetIDOfName(
            _In_z_ LPCOLESTR lpsz, 
            _Out_ DISPID* pdispid) throw()
        {
            return p->GetIDsOfNames(IID_NULL, const_cast<LPOLESTR*>(&lpsz), 1, LOCALE_USER_DEFAULT, pdispid);
        }
        // Invoke a method by DISPID with no parameters
        _Check_return_ HRESULT Invoke0(
            _In_ DISPID dispid, 
            _Out_opt_ VARIANT* pvarRet = NULL) throw()
        {
            DISPPARAMS dispparams = { NULL, NULL, 0, 0};
            return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL);
        }
        // Invoke a method by name with no parameters
        _Check_return_ HRESULT Invoke0(
            _In_z_ LPCOLESTR lpszName, 
            _Out_opt_ VARIANT* pvarRet = NULL) throw()
        {
            HRESULT hr;
            DISPID dispid;
            hr = GetIDOfName(lpszName, &dispid);
            if (SUCCEEDED(hr))
                hr = Invoke0(dispid, pvarRet);
            return hr;
        }
        // Invoke a method by DISPID with a single parameter
        _Check_return_ HRESULT Invoke1(
            _In_ DISPID dispid, 
            _In_ VARIANT* pvarParam1, 
            _Out_opt_ VARIANT* pvarRet = NULL) throw()
        {
            DISPPARAMS dispparams = { pvarParam1, NULL, 1, 0};
            return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL);
        }
        // Invoke a method by name with a single parameter
        _Check_return_ HRESULT Invoke1(
            _In_z_ LPCOLESTR lpszName, 
            _In_ VARIANT* pvarParam1, 
            _Out_opt_ VARIANT* pvarRet = NULL) throw()
        {         
            DISPID dispid;
            HRESULT hr = GetIDOfName(lpszName, &dispid);
            if (SUCCEEDED(hr))
                hr = Invoke1(dispid, pvarParam1, pvarRet);
            return hr;
        }
        // Invoke a method by DISPID with two parameters
        _Check_return_ HRESULT Invoke2(
            _In_ DISPID dispid, 
            _In_ VARIANT* pvarParam1, 
            _In_ VARIANT* pvarParam2, 
            _Out_opt_ VARIANT* pvarRet = NULL) throw();
        // Invoke a method by name with two parameters
        _Check_return_ HRESULT Invoke2(
            _In_z_ LPCOLESTR lpszName, 
            _In_ VARIANT* pvarParam1, 
            _In_ VARIANT* pvarParam2, 
            _Out_opt_ VARIANT* pvarRet = NULL) throw()
        {
            DISPID dispid;
            HRESULT hr = GetIDOfName(lpszName, &dispid);
            if (SUCCEEDED(hr))
                hr = Invoke2(dispid, pvarParam1, pvarParam2, pvarRet);
            return hr;
        }
        // Invoke a method by DISPID with N parameters
        _Check_return_ HRESULT InvokeN(
            _In_ DISPID dispid, 
            _In_ VARIANT* pvarParams, 
            _In_ int nParams, 
            _Out_opt_ VARIANT* pvarRet = NULL) throw()
        {
            DISPPARAMS dispparams = { pvarParams, NULL, nParams, 0};
            return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL);
        }
        // Invoke a method by name with Nparameters
        _Check_return_ HRESULT InvokeN(
            _In_z_ LPCOLESTR lpszName, 
            _In_ VARIANT* pvarParams, 
            _In_ int nParams, 
            _Out_opt_ VARIANT* pvarRet = NULL) throw()
        {
            HRESULT hr;
            DISPID dispid;
            hr = GetIDOfName(lpszName, &dispid);
            if (SUCCEEDED(hr))
                hr = InvokeN(dispid, pvarParams, nParams, pvarRet);
            return hr;
        }
        _Check_return_ static HRESULT PutProperty(
            _In_ IDispatch* p, 
            _In_ DISPID dwDispID, 
            _In_ VARIANT* pVar) throw()
        {
            ATLASSERT(p);
            ATLASSERT(pVar != NULL);
            if (pVar == NULL)
                return E_POINTER;
            
            if(p == NULL)
                return E_INVALIDARG;
            
            ATLTRACE(atlTraceCOM, 2, _T("CPropertyHelper::PutProperty
    "));
            DISPPARAMS dispparams = {NULL, NULL, 1, 1};
            dispparams.rgvarg = pVar;
            DISPID dispidPut = DISPID_PROPERTYPUT;
            dispparams.rgdispidNamedArgs = &dispidPut;
    
            if (pVar->vt == VT_UNKNOWN || pVar->vt == VT_DISPATCH || 
                (pVar->vt & VT_ARRAY) || (pVar->vt & VT_BYREF))
            {
                HRESULT hr = p->Invoke(dwDispID, IID_NULL,
                    LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF,
                    &dispparams, NULL, NULL, NULL);
                if (SUCCEEDED(hr))
                    return hr;
            }
            return p->Invoke(dwDispID, IID_NULL,
                    LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
                    &dispparams, NULL, NULL, NULL);
        }
        _Check_return_ static HRESULT GetProperty(
            _In_ IDispatch* p, 
            _In_ DISPID dwDispID, 
            _Out_ VARIANT* pVar) throw()
        {
            ATLASSERT(p);
            ATLASSERT(pVar != NULL);
            if (pVar == NULL)
                return E_POINTER;
            
            if(p == NULL)
                return E_INVALIDARG;
                
            ATLTRACE(atlTraceCOM, 2, _T("CPropertyHelper::GetProperty
    "));
            DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
            return p->Invoke(dwDispID, IID_NULL,
                    LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
                    &dispparamsNoArgs, pVar, NULL, NULL);
        }
    };
    atlcomcli.h部分代码

    上面这些其实也都是调用了Invoke函数,当然你如果不想用它帮你封装过的这些函数的话,你可以自行调用比上面这些更原始的Invoke,或者重新封装一下它。

    总而言之,当你做这就事的时候一定要不停的查阅MSDN,没了它你就是在蒙着眼睛摸象加自欺欺人。

  • 相关阅读:
    部门创建注意问题
    我的技术博客开通啦~
    听侯钟雷老师的讲座,确认了几个问题。
    Dynamics CRM 批量添加用户时,报错:Server was unable to process request.
    汉字的Unicode范围(转)
    转载:Apache1.1 post请求无body的bug
    转载:Android有效解决加载大图片时内存溢出的问题
    2.2之前的webkit crash问题
    转载:Expect:100Continue & HTTP 417 Expectation
    城市旅游问题
  • 原文地址:https://www.cnblogs.com/hyb1/p/3309207.html
Copyright © 2020-2023  润新知