进程间通信方法:接口Variant封装包参数传递

    技术2022-05-11  45

    利用接口技术进行进程通信,由于是跨进程,指针是不能传递的,COM提供了Variant类型的参数传递方式 。 如:进程P1把数据放在Var中, 调用进程2 P2.SetData(VARIANT Var)进行传送时,系统会进程1的Var数据在进程2的内存空间copy一份一模一样的数据,然后才调用真正的SetData。 方便操作Variant的类 CVariantBuffer.h #pragma once   // 1. Access buffer from ByteArray Variant /*     CVariantBuffer vbuf;      if( SUCCEEDED(vbuf.Lock(&Var)))      {        char *buf = (char *)vbuf.getBuffer();        ULONG len = vbuf.getLength();             printf(buf);        ...        vbuf.Unlock();      } */ // 2. Create Variant and copy data from Buffer /*     VARIANT *pVar = CVariantBuffer::CreateVariant(buf, max);     ...     VariantClear(pVar); */   class CVariantBuffer { protected :     VARIANT * m_pVariant;     void   * m_pBuffer;     ULONG     m_dwLength;     bool    m_bLockData;   public :     CVariantBuffer()     {        m_bLockData = false;        m_dwLength = 0;        m_bLockData = false;        m_pBuffer = NULL;     }       HRESULT Lock(VARIANT * pVariant)     {        m_dwLength = 0;        m_bLockData = false;        m_pBuffer = NULL;          if(pVariant == NULL) return E_INVALIDARG;          if((pVariant->vt & VT_ARRAY) && ((pVariant->vt & VT_UI1) || (pVariant->vt & VT_I1)))        {            m_pVariant = pVariant;            SAFEARRAY * psa = pVariant->parray;            if(psa && (psa->cbElements != 1)) return E_INVALIDARG;            HRESULT hr = SafeArrayAccessData(psa, &m_pBuffer);            if(FAILED(hr) ) return hr;            m_bLockData = true;            m_dwLength = psa->rgsabound[0].cElements;            return S_OK;        }        else return E_INVALIDARG;     }       HRESULT Unlock()     {        if(m_bLockData && (m_pBuffer != NULL))        {            SafeArrayUnaccessData(m_pVariant->parray);            CVariantBuffer();            return S_OK;        }        return E_FAIL;     }       void * getBuffer()     {        return m_pBuffer;     }       ULONG getLength()     {        return m_dwLength;     }       // create VARIANT, copy buf data to variant     // you must use VariantClear() to free     static VARIANT * CreateVariant(const void * pBuf, ULONG nLenght)     {        // SAFEARRAY        SAFEARRAY *psa;        SAFEARRAYBOUND rgsabound[1];        BYTE *p;          rgsabound[0].cElements = nLenght;        rgsabound[0].lLbound = 0;        psa = SafeArrayCreate(VT_UI1, 1, rgsabound);          // copy data        SafeArrayAccessData(psa, (void **)&p);        CopyMemory(p, pBuf, nLenght);        SafeArrayUnaccessData(psa);          // VARIANT          VARIANT * pv = new VARIANT;        pv->vt = VT_ARRAY | VT_UI1;        pv->parray = psa;             return pv;     } };     Server实现接口主程序 // CSample.h : Declaration of the CSample   #pragma once #include "resource.h"       // main symbols #include "CVariantBuffer.h"     #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA) #error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms." #endif     // ISample [     object,     uuid("88FBCC25-E252-4E3F-859D-809CCFDBDB1F"),     dualhelpstring("ISample Interface"),     pointer_default(unique) ] __interface ISample : IDispatch {     [id(1), helpstring("method GetData")] HRESULT GetData([out] VARIANT** ppVar);     [id(2), helpstring("method SetData")] HRESULT SetData([in] VARIANT Var); };       // CSample   [     coclass,     default(ISample),     threading(apartment),     vi_progid("VariantServer.Sample"),     progid("VariantServer.Sample.1"),     version(1.0),     uuid("9A4AB3AE-4710-42B7-B360-120478BF8D51"),     helpstring("Sample Class") ] class ATL_NO_VTABLE CSample :     public ISample { public :     CSample()     {     }         DECLARE_PROTECT_FINAL_CONSTRUCT()       HRESULT FinalConstruct()     {        return S_OK;     }       void FinalRelease()     {     }   public :           STDMETHODIMP GetData(VARIANT** ppVar)     {        const int max = 1000;        char buf[max];          for(int i = 0; i< max; i++)            buf[i] = 'A';        buf[max-1] = '/0';          *ppVar = CVariantBuffer::CreateVariant(buf, max);             return S_OK;     }         STDMETHODIMP SetData(VARIANT Var)     {        CVariantBuffer vbuf;        if( vbuf.Lock(&Var) == S_OK)        {            char *buf = (char *)vbuf.getBuffer();            ULONG len = vbuf.getLength();                 printf(buf);            for(int i = 0; i< len - 1; i++)            buf[i] = 'C';              vbuf.Unlock();        }        return S_OK;     } };       Clietn测试接口程序 // VariantClient.cpp : Defines the entry point for the console application. //   #include "stdafx.h" #include "../VariantServer/_VariantServer.h" #include "../VariantServer/CVariantBuffer.h"   static const GUID IID_ISample = { 0x88FBCC25,0xE252,0x4E3F, {0x85,0x9D,0x80,0x9C,0xCF,0xDB,0xDB,0x1F} };   //("9A4AB3AE-4710-42B7-B360-120478BF8D51"), static const GUID CLSID_CSample = {0x9A4AB3AE,0x4710,0x42B7, {0xB3,0x60,0x12,0x04,0x78,0xBF,0x8D,0x51}};     int _tmain(int argc, _TCHAR* argv[]) {             ISample * pSample;     HRESULT hr;     CoInitialize(NULL);       hr = CoCreateInstance(CLSID_CSample, NULL, CLSCTX_LOCAL_SERVER, IID_ISample, (LPVOID *)&pSample);     if(SUCCEEDED(hr))     {          // GetData        VARIANT * pV;        pSample->GetData(&pV);          if(pV->vt && VT_ARRAY)        {            CVariantBuffer vbuf;            if(SUCCEEDED(vbuf.Lock(pV)))            {               char *buf = (char *)vbuf.getBuffer();               ULONG len = vbuf.getLength();                    printf(buf);                             // fill buf used 'B'               for(int i = 0; i< len - 1; i++) buf[i] = 'B';                 vbuf.Unlock();                    pSample->SetData(*pV);                 // pV be not changed to 'C'            }        }          VariantClear(pV);          pSample->Release();     }         //getchar();       CoUninitialize();             return 0; }    

    最新回复(0)