• ATL 核心COM继承类之IDispatchImpl及调用


    实现

    先看IDispatch接口,如同反射

    interface IDispatch : IUnknown {                   
        HRESULT GetTypeInfoCount([out] UINT * pctinfo);
    
        HRESULT GetTypeInfo([in] UINT iTInfo,          
            [in] LCID lcid,                            
            [out] ITypeInfo ** ppTInfo);               
    
        HRESULT GetIDsOfNames([in] REFIID riid,        
            [in, size_is(cNames)] LPOLESTR * rgszNames,
            [in] UINT cNames,                          
            [in] LCID lcid,                            
            [out, size_is(cNames)] DISPID * rgDispId); 
    
        HRESULT Invoke([in] DISPID dispIdMember,       
            [in] REFIID riid,                          
            [in] LCID lcid,                            
            [in] WORD wFlags,                          
            [in, out] DISPPARAMS * pDispParams,        
            [out] VARIANT * pVarResult,                
            [out] EXCEPINFO * pExcepInfo,              
            [out] UINT * puArgErr);                    
    }                
    

    要实现IDispatch接口的动作是差不多的

    class CPenguin :
        public CComObectRootEx<CComSingleThreadModel>,
        public IBird,
        public ISnappyDresser,
        public IPenguin {
    public:
        CPenguin() : m_pTypeInfo(0) {
            IID*      pIID   = &IID_IPenguin;
            GUID*     pLIBID = &LIBID_BIRDSERVERLib;
            WORD      wMajor = 1;
            WORD      wMinor = 0;
            ITypeLib* ptl = 0;
            HRESULT hr = LoadRegTypeLib(*pLIBID, wMajor, wMinor,
                0, &ptl);
            if( SUCCEEDED(hr) ) {
                hr = ptl->GetTypeInfoOfGuid(*pIID, &m_pTypeInfo);
                ptl->Release();
            }
        }
    
        virtual ~Penguin() {
            if( m_pTypeInfo ) m_pTypeInfo->Release();
        }
    
        BEGIN_COM_MAP(CPenguin)
            COM_INTERFACE_ENTRY(IBird)
            COM_INTERFACE_ENTRY(ISnappyDresser)
            COM_INTERFACE_ENTRY(IDispatch)
            COM_INTERFACE_ENTRY(IPenguin)
        END_COM_MAP()
    
        // IDispatch methods
        STDMETHODIMP GetTypeInfoCount(UINT *pctinfo) {
            return (*pctinfo = 1), S_OK;
        }
        STDMETHODIMP GetTypeInfo(UINT ctinfo, LCID lcid,
            ITypeInfo **ppti) {
                if( ctinfo != 0 ) return (*ppti = 0), DISP_E_BADINDEX;
                return (*ppti = m_pTypeInfo)->AddRef(), S_OK;
        }
    
        STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR **rgszNames,
            UINT cNames, LCID lcid, DISPID *rgdispid) {
                return m_pTypeInfo->GetIDsOfNames(rgszNames, cNames,
                    rgdispid);
        }
    
        STDMETHODIMP Invoke(DISPID dispidMember,
            REFIID riid,
            LCID lcid,
            WORD wFlags,
            DISPPARAMS *pdispparams,
            VARIANT *pvarResult,
            EXCEPINFO *pexcepinfo,
            UINT *puArgErr) {
                return m_pTypeInfo->Invoke(static_cast<IPenguin*>(this),
                    dispidMember, wFlags,
                    pdispparams, pvarResult,
                    pexcepinfo, puArgErr);
        }
        // IBird, ISnappyDresser and IPenguin methods...
    private:
        ITypeInfo* m_pTypeInfo;
    };
    
    

    以IDispatchImpl替代

    class CPenguin :
        public CComObjectRootEx<CComMultiThreadModel>,
        public IBird,
        public ISnappyDresser,
        public IDispatchImpl<IPenguin, &IID_IPenguin> {
    public:
        BEGIN_COM_MAP(CPenguin)
            COM_INTERFACE_ENTRY(IBird)
            COM_INTERFACE_ENTRY(ISnappyDresser)
            COM_INTERFACE_ENTRY(IDispatch)
            COM_INTERFACE_ENTRY(IPenguin)
        END_COM_MAP()
        // IBird, ISnappyDresser and IPenguin methods...
    };
    

    IDispatchImpl具体实现

    template <class T, const IID* piid = &__uuidof(T), const GUID* plibid = &CAtlModule::m_libid, WORD wMajor = 1,
    WORD wMinor = 0, class tihclass = CComTypeInfoHolder>
    class ATL_NO_VTABLE IDispatchImpl : 
        public T
    {
    public:
        typedef tihclass _tihclass;
    // IDispatch
        STDMETHOD(GetTypeInfoCount)(_Out_ UINT* pctinfo)
        {
            if (pctinfo == NULL) 
                return E_POINTER; 
            *pctinfo = 1;
            return S_OK;
        }
        STDMETHOD(GetTypeInfo)(
            _In_ UINT itinfo, 
            _In_ LCID lcid, 
            _Deref_out_ ITypeInfo** pptinfo)
        {
            return _tih.GetTypeInfo(itinfo, lcid, pptinfo);
        }
        STDMETHOD(GetIDsOfNames)(
            _In_ REFIID riid, 
            _In_count_(cNames) _Deref_pre_z_ LPOLESTR* rgszNames, 
            _In_ UINT cNames,
            _In_ LCID lcid, 
            _Out_ DISPID* rgdispid)
        {
            return _tih.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
        }
        STDMETHOD(Invoke)(
            _In_ DISPID dispidMember, 
            _In_ REFIID riid,
            _In_ LCID lcid, 
            _In_ WORD wFlags, 
            _In_ DISPPARAMS* pdispparams, 
            _Out_opt_ VARIANT* pvarResult,
            _Out_opt_ EXCEPINFO* pexcepinfo, 
            _Out_opt_ UINT* puArgErr)
        {
            return _tih.Invoke((IDispatch*)this, dispidMember, riid, lcid,
            wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
        }
    
    #ifdef _ATL_DLL_IMPL
        // Do not cache type info if it is used in the ATL dll
        IDispatchImpl() : _tih(piid, plibid, wMajor, wMinor)
        {
        }
        virtual ~IDispatchImpl()
        {
        }
    
    protected:
        _tihclass _tih;
        HRESULT GetTI(
            _In_ LCID lcid, 
            _Deref_out_ ITypeInfo** ppInfo)
        {
            return _tih.GetTI(lcid, ppInfo);
        }
    
    #else
    
    protected:
        static _tihclass _tih;
        static HRESULT GetTI(
            _In_ LCID lcid, 
            _Deref_out_ ITypeInfo** ppInfo)
        {
            return _tih.GetTI(lcid, ppInfo);
        }
    
    #endif
    };
    

    调用IDispatch接口

    很麻烦的一个过程,如下动态调用Add方法

    // component IDL file
    [
        object,
        uuid(2F6C88D7-C2BF-4933-81FA-3FBAFC3FC34B),
        dual,
    ]
    interface ICalc : IDispatch {
        [id(1)] HRESULT Add([in] DOUBLE Op1,
            [in] DOUBLE Op2, [out,retval] DOUBLE* Result);
    };
    
    // client.cpp
    HRESULT CallAdd(IDispatch* pdisp) {
        // Get the DISPID
        LPOLESTR pszMethod = OLESTR("Add");
        DISPID dispid;
        hr = pdisp->GetIDsOfNames(IID_NULL,
            &pszMethod,
            1,
            LOCALE_SYSTEM_DEFAULT,
            &dispid);
    
        if (FAILED(hr))
            return hr;
    
        // Set up the parameters
        DISPPARAMS dispparms;
        memset(&dispparms, 0, sizeof(DISPPARAMS));
        dispparms.cArgs = 2;
    
        // Parameters are passed right to left
        VARIANTARG rgvarg[2];
        rgvarg[0].vt = VT_R8;
        rgvarg[0].dblVal = 6;
        rgvarg[1].vt = VT_R8;
        rgvarg[1].dblVal = 7;
    
        dispparms.rgvarg = &rgvarg[0];
    
        // Set up variable to hold method return value
        VARIANTARG vaResult;
        ::VariantInit(&vaResult);
    
        // Invoke the method
        hr = pdisp->Invoke(dispid,
            IID_NULL,
            LOCALE_SYSTEM_DEFAULT,
            DISPATCH_METHOD,
            &dispparms,
            &vaResult,
            NULL,
            NULL);
    
        // vaResult now holds sum of 6 and 7
    }
    

    CComPtr<IDispatch>提供了很多的便利方法

    image

    调用如下:

    HRESULT TheEasyWay( IDispatch *spCalcDisp ) {
        CComPtr< IDispatch > spCalcDisp( pCalcDisp );
    
        CComVariant varOp1( 6.0 );
        CComVariant varOp2( 7.0 );
        CComVariant varResult;
        HRESULT hr = spCalcDisp.Invoke2( OLESTR( "Add" ),
            &varOp1, &varOp2, &varResult );
        // varResult now holds sum of 6 and 7
    }
    
  • 相关阅读:
    精确覆盖DLX算法模板另一种写法
    Hdu3498-whosyourdaddy(精确覆盖模板题)
    精确覆盖DLX算法模板
    Object2Map
    Use ResourceBundle read properties file.
    Kendo UI Example(grid)
    Kendo 日期控件
    Spring mvc 中文乱码问题解决方法
    Thread communication java.util.concurrent.locks.Condition 用法(二)
    Thread communication java.util.concurrent.locks.Condition 用法(一)
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/2674935.html
Copyright © 2020-2023  润新知