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

  利用接口技术进行进程通信,由于是跨进程,指针是不能传递的,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;
}
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值