首先,idl文件my.idl:
[ |
服务器端实现:
#include"stdafx.h" |
UseProtseqEq ok
Register if ok
客户端代码:
// myclient.cpp : Defines the entry point for the console application. |
szString=ncacn_ip_tcp:localhost[4747]
此时,服务器端显示:
server:Hello RPC World!
多次启动客户端,上面这句话显示多次。
---------------------------------------------------------
自己写的com客户端的代码,放到blog里面作为备份。
点击(此处)折叠或打开
- #include<algorithm>
- #include<cassert>
- #include<type_traits>
- #include<iostream>
- #include<iterator>
- using namespace std;
- #import "..\ATLProject1\Debug\ATLProject1.tlb" no_namespace raw_native_types named_guids
- #import "..\ATLProject3\Debug\ATLProject3.tlb" no_namespace raw_native_types named_guids
- #import "..\ATLProject5\Debug\ATLProject5.tlb" no_namespace raw_native_types named_guids
- #import "..\cs_ClassLibrary1\bin\Debug\cs_ClassLibrary1.tlb" no_namespace raw_native_types named_guids
- void UseCSharpCom()
- {
- MyCom_InterfacePtr p(CLSID_Class1,NULL,CLSCTX_ALL);
- printf("%d\n",p->Add(3,9));
- p.Release();
- }
- void UsingGeneratedPtr()
- {
- IMyErrPtr p(CLSID_MyErr,NULL,CLSCTX_ALL);
- LONG ret;
- HRESULT r=p->Sub(&ret,33,48);
- printf("%d\n",ret);
- p.Release();
- }
- void fv(){}
- short fs(){return 0;}
- int fi(){return 0;}
- double fd(){return 0;}
- int (*pfi);
- short (*pfs);
- using namespace std;
- template <class T, size_t n>
- char (*pc(T (&arr)[n]))[n];
- void ApiDispatch()
- {
- CLSID id;
- HRESULT hr=CLSIDFromProgID(L"my.fun",&id);
- assert( SUCCEEDED( hr ) );
- CoInitialize(NULL);
- IDispatch* pDisp=NULL;
- hr=CoCreateInstance(id,NULL,CLSCTX_ALL,IID_IDispatch,(void**)&pDisp);
- assert( SUCCEEDED( hr ) );
- LPOLESTR pstrName=L"Add";
- DISPID fID(0);
- hr=pDisp->GetIDsOfNames(IID_NULL,&pstrName,1,LOCALE_SYSTEM_DEFAULT,&fID);
- assert( SUCCEEDED( hr ) );
- VARIANT v[2],vResult;
- v[0].vt=VT_I4;
- v[1].vt=VT_I4;
- v[0].lVal=33;
- v[1].lVal=48;
- DISPPARAMS param={v,NULL,2,0};
- hr=pDisp->Invoke(fID,IID_NULL,LOCALE_SYSTEM_DEFAULT,DISPATCH_METHOD,¶m,&vResult,NULL,NULL);
- assert( SUCCEEDED( hr ) );
- printf("result=%d\n",vResult.lVal);
- pDisp->Release();
- CoUninitialize();
- }
- void ATLDispatch()
- {
- CLSID id;
- HRESULT hr=CLSIDFromProgID(L"my.fun",&id);
- assert( SUCCEEDED( hr ) );
- CoInitialize(NULL);
- CComDispatchDriver spDisp;
- hr=CoCreateInstance(id,NULL,CLSCTX_ALL,IID_IUnknown,(void**)&spDisp);
- assert( SUCCEEDED( hr ) );
- CComVariant v[3],vResult;
- v[0]=33;
- v[1]=48;
- v[2]=2;
- hr=spDisp.InvokeN(L"Add3",v,3,&vResult);
- assert( SUCCEEDED( hr ) );
- printf("result=%d\n",vResult.lVal);
- spDisp.Release();
- CoUninitialize();
- }
- void f()
- {
- //
- // 1,2
- // 11,22
- // 31,32
- // 41,42
- // 51,52
- //
- #define dim 2
- SAFEARRAYBOUND b[dim];
- b[0].cElements=5;
- b[0].lLbound=0;
- b[1].cElements=2;
- b[1].lLbound=0;
- SAFEARRAY* psa=SafeArrayCreate(VT_I4,dim,b);
- long Idx[dim];
- int x=0;
- for(size_t i=0;i<5;++i)
- {
- for(size_t j=0;j<2;++j)
- {
- Idx[0]=i;
- Idx[1]=j;
- x=i*10+j+1;
- SafeArrayPutElement(psa,Idx,&x);
- }
- }
- int* pi=0;;
- HRESULT hr=SafeArrayAccessData(psa,(void**)&pi);
- copy(pi,pi+10,ostream_iterator<int>(cout,","));
- SafeArrayUnaccessData(psa);
- SafeArrayDestroy(psa);
- }
- class CSink: public ICallBack
- {
- public:
- STDMETHODIMP QueryInterface(const struct _GUID&iid,void**ppv)
- {
- *ppv=this;
- return S_OK;
- }
- ULONG __stdcall AddRef(void) {return 1;}
- ULONG __stdcall Release(void){return 0;}
- STDMETHODIMP raw_Fire_Result(long nResult)
- {
- cout<<"fire"<<nResult<<endl;
- return S_OK;
- }
- };
- void UseEventClient()
- {
- cout<<__FUNCTION__<<endl;
- CComQIPtr<IEvent1> pe;
- pe.CoCreateInstance(CLSID_Event1,NULL,CLSCTX_ALL);
- if(pe)
- {
- cout<<"Call com event"<<endl;
- CSink client1;
- ULONG cookie=30;
- pe->Register(&client1,&cookie);
- pe->Add(33,99);
- pe->Unregister(cookie);
- }
- pe.Release();
- }
- void UseSafeArray()
- {
- CComSafeArray<int> a(2,0);
- CComSafeArrayBound bounds[]={(2,0),(3,0),(4,0)};
- CComSafeArray<int> sa(bounds,_countof(bounds));
- long index[]={3,2,1};
- sa.MultiDimSetAt(index,200);
- }
- IFunPtr pf;
- UINT __stdcall mytf(void* pArg)
- {
- cout<<"Thread function"<<endl;
- CoInitialize(NULL);
- HRESULT hr=pf.CreateInstance(CLSID_Fun,NULL);//,CLSCTX_REMOTE_SERVER);
- cout<<pf->Add(2,3)<<endl;
- Sleep(2000);
- cout<<"Thread ends"<<endl;
- pf.Release();
- CoUninitialize();
- _endthreadex(0);
- return 0;
- }
- void f3()
- {
- //_beginthreadex(NULL,0,mytf,NULL,0,NULL);//如何Join?
- CoInitialize(NULL);
- IFun* p1,*p2;
- HRESULT hr=::CoCreateInstance(CLSID_Fun,NULL,CLSCTX_ALL,IID_IFun,(void**)&p1);
- hr=::CoCreateInstance(CLSID_Fun,NULL,CLSCTX_ALL,IID_IFun,(void**)&p2);
- assert(p1!=p2);
- p2->Release();
- p1->Release();
- CoUninitialize();
- }
- class Father
- {
- public:
- int i;
- Father(){i=22;}
- virtual void f(){printf("f:%d\n",i);}
- virtual void g(){printf("g:%d\n",i);}
- virtual void h(){printf("h:%d\n",i);}
- };
- class Child:public Father
- {
- public:
- void f(){printf("child f\n");}
- };
- typedef void (__thiscall *pFather)(Father*);
- void fVTable()
- {
- Father* pf=new Father;
- Father* pf2=new Father;
- pf->f();
- printf("pf =%p\npf->i=%p\n",pf,&(pf->i));
- pFather *pVtable=*(pFather**)(pf);
- pVtable[0](pf);
- pVtable[1](pf);
- pVtable[2](pf);
- delete pf;
- delete pf2;
-
- Father* pc=new Child;
- printf("Father vtable=%p,%p\nChild vtable=%p\n",
- *(int*)(pf),
- *(int*)(pf2),
- *(int*)(pc));
- (*(pFather**)(pc))[0](pc);
- }
- void UsingISupportError(bool fThrowException=false)
- {
- IMyErrPtr p(CLSID_MyErr,NULL,CLSCTX_ALL);
- try
- {
- HRESULT hr;
- if(fThrowException)
- {
- LONG ret=0;
- hr=p->Sub(&ret,33,81);//ATL CComCoClass::Error will throw an exception
- printf("%d\n",ret);
- }
- else
- {
- hr=p->raw_Sub2(LONG());
- CComQIPtr<ISupportErrorInfo> spSEI=p;
- if(spSEI)
- {
- puts("support!");
- hr=spSEI->InterfaceSupportsErrorInfo(IID_IMyErr);
- if(SUCCEEDED(hr))
- {
- CComQIPtr<IErrorInfo> spError;
- hr=GetErrorInfo(0,&spError);
- if(SUCCEEDED(hr))
- {
- CComBSTR bstr;
- spError->GetDescription(&bstr);
- LPWSTR s1=bstr;
- LPCTSTR s2=OLE2CT(s1);
- _tprintf(_T("%s\n"),s2);
- }
- }
- }
- spSEI.Release();
- }
- }
- catch(_com_error &e)
- {
- LPWSTR s=e.Description();
- _tprintf(_T("%s\n"),OLE2CT(s));
- }
- p.Release();
- }
- void UseCComSafeArray()
- {
- CComSafeArrayBound bounds[]={CComSafeArrayBound(2,0),CComSafeArrayBound(3,0),CComSafeArrayBound(4,0)};
- CComSafeArray<int> arr(bounds,_countof(bounds));
- SAFEARRAY* psa=arr.m_psa;
- cout<<psa->cbElements<<','<<psa->cDims<<endl;
- cout<<arr.GetCount(0)<<','<<arr.GetCount(1)<<','<<arr.GetCount(2)<<endl;
- CComVariant v=psa;//::SafeArrayCopy() is called
- }
- /*
- void MFCDispatch()
- {
- CoInitialize(NULL);
- CFun f;
- f.CreateDispatch(L"my.fun");
- printf("%d\n",f.Add(33,48));
- f.ReleaseDispatch();
- CoUninitialize();
- }
- */
- class CPropertyBag: public IPropertyBag
- {
- public:
- STDMETHODIMP CPropertyBag::QueryInterface(const struct _GUID &iid,void ** ppv)
- {
- *ppv = this;
- return S_OK;
- }
- STDMETHODIMP_(ULONG) CPropertyBag::AddRef(void) {return 1;}
- STDMETHODIMP_(ULONG) CPropertyBag::Release(void){return 0;}
- STDMETHODIMP CPropertyBag::Read(LPCOLESTR pszPropName,VARIANT *pVar,IErrorLog *pErrorLog)
- {
- cout<<__FUNCTION__<<','<<pVar->vt<<endl;
- if( pVar->vt == VT_BSTR )
- {
- pVar->bstrVal=OLE2BSTR(L"mystring");
- return S_OK;
- }
- else if( pVar->vt == VT_I4 )
- {
- pVar->lVal=207;
- return S_OK;
- }
- else return E_FAIL;
- }
- STDMETHODIMP CPropertyBag::Write(LPCOLESTR pszPropName,VARIANT *pVar)
- {
- return S_OK;
- }
- };
- void UsePropBag()
- {
- IPersistPropertyBagPtr ptr(CLSID_Property,NULL,CLSCTX_ALL);
- if(ptr)
- {
- CPropertyBag bag;
- ptr->Load(&bag,NULL);
- ptr.Release();
- }
- }
- void UseAggregation()
- {
- IMyAggrPtr sp1(CLSID_MyAggr,NULL,CLSCTX_ALL);
- IFooPtr spFoo;
- sp1->QueryInterface(&spFoo);
- cout<<spFoo->Add(3,4)<<endl;
- spFoo.Release();
- sp1.Release();
- }
- class CPSink : public IDispatch
- {
- public:
- STDMETHODIMP QueryInterface(const struct _GUID &iid,void ** ppv)
- {
- *ppv=this;
- return S_OK;
- }
- STDMETHODIMP_(ULONG) AddRef(void){return 1;}
- STDMETHODIMP_(ULONG) Release(void){return 0;}
- STDMETHODIMP GetTypeInfoCount(unsigned int *){return E_NOTIMPL;}
- STDMETHODIMP GetTypeInfo(unsigned int,unsigned long,struct ITypeInfo ** ){return E_NOTIMPL;}
- STDMETHODIMP GetIDsOfNames(const IID &,LPOLESTR *,UINT,LCID,DISPID *){return E_NOTIMPL;}
- STDMETHODIMP Invoke(
- long dispID,
- const struct _GUID &,
- unsigned long,
- unsigned short,
- struct tagDISPPARAMS * pParams,
- struct tagVARIANT *,
- struct tagEXCEPINFO *,
- unsigned int *)
- {
- switch(dispID)
- {
- case 1:
- _tprintf(_T("Result=%d\n"),pParams->rgvarg[0].lVal);
- break;
- default:
- break;
- }
- return S_OK;
- }
- };
- void TestConnectionPoint()
- {
- ICP1Ptr spCP1(CLSID_CP1,NULL,CLSCTX_ALL);
- CComQIPtr<IConnectionPointContainer> spContainer=spCP1;
- CComQIPtr<IConnectionPoint> spCP;
- HRESULT hr=spContainer->FindConnectionPoint(DIID__ICP1Events,&spCP);
- CPSink obj;
- DWORD dwCookie;
- spCP->Advise(&obj,&dwCookie);
- spCP1->Add(3,9);
- spCP->Unadvise(dwCookie);
- spCP.Release();
- spContainer.Release();
- spCP1.Release();
- }
- struct UseStream
- {
- HRESULT hr; // 函数执行返回值
- IStorage *pStg;
- IStorage *pSub;
- IStream *pStm;
- UseStream()
- {
- IStorage *pStg = NULL; // 根存储接口指针
- IStorage *pSub = NULL; // 子存储接口指针
- IStream *pStm = NULL; // 流接口指针
- CreateDoc();
- }
- ~UseStream()
- {
- CloseDoc();
- }
- void CreateDoc()
- {
- hr = ::StgCreateDocfile( // 建立复合文件
- L"d:\\c.stg", // 文件名称
- STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, // 打开方式
- 0, // 保留参数
- &pStg); // 取得根存储接口指针
- assert( SUCCEEDED(hr) ); // 为了突出重点,简化程序结构,所以使用了断言。
- // 在实际的程序中则要使用条件判断和异常处理
- hr = pStg->CreateStorage( // 建立子存储
- L"SubStg", // 子存储名称
- STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,
- 0,0,
- &pSub); // 取得子存储接口指针
- assert( SUCCEEDED(hr) );
- hr = pSub->CreateStream( // 建立流
- L"Stm", // 流名称
- STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,
- 0,0,
- &pStm); // 取得流接口指针
- assert( SUCCEEDED(hr) );
- }
- void CloseDoc()
- {
- if( pStm ) pStm->Release();// 释放流指针
- if( pSub ) pSub->Release();// 释放子存储指针
- if( pStg ) pStg->Release();// 释放根存储指针
- }
- void WriteSample()
- {
- hr = pStm->Write( // 向流中写入数据
- "Hello", // 数据地址
- 5, // 字节长度(注意,没有写入字符串结尾的\0)
- NULL); // 不需要得到实际写入的字节长度
- assert( SUCCEEDED(hr) );
-
- IPersistStreamInitPtr spStream(CLSID_MySingle,NULL,CLSCTX_ALL);
- if(spStream)
- {
- spStream->InitNew();
- spStream->Save(pStm,TRUE);
- spStream.Release();
- }
- }
- void WriteMarshalToDocument()
- {
- IFunPtr ptr(CLSID_Fun,NULL,CLSCTX_ALL);
- assert(ptr);
- CoMarshalInterface(pStm,IID_IFun,ptr,MSHCTX_LOCAL,NULL,MSHLFLAGS_NORMAL);
- ptr.Release();
- }
- };
- void SampleCreateDoc()
- {
- UseStream obj1;
- obj1.WriteMarshalToDocument();
- }
- void MarshalOleAutomation()
- {
- IE2Ptr ptr(CLSID_E2,NULL,CLSCTX_ALL);
- assert(ptr);
- IStream* pStm;
- HRESULT hr = CoMarshalInterThreadInterfaceInStream(IID_IE2,ptr,&pStm);
- assert(SUCCEEDED(hr));
- IE2Ptr pGet;
- hr=CoGetInterfaceAndReleaseStream(pStm,IID_IE2,(LPVOID*)&pGet);
- assert(SUCCEEDED(hr));
- cout<<pGet->Add(44,3)<<endl;//自定义接口+支持oleautomation
- ptr.Release();
- }
- class WriteMarshalToMemory
- {
- static IStream* pStm;
- public:
- static DWORD WINAPI f(void*)
- {
- CoInitialize(NULL);
- IE2Ptr pGet;
- HRESULT hr=CoGetInterfaceAndReleaseStream(pStm,IID_IE2,(LPVOID*)&pGet);
- assert(SUCCEEDED(hr));
- cout<<pGet->Add(44,29)<<endl;
- CoUninitialize();
- return 0;
- }
- WriteMarshalToMemory()
- {
- IE2Ptr ptr(CLSID_E2,NULL,CLSCTX_ALL);
- assert(ptr);
- HRESULT hr = CoMarshalInterThreadInterfaceInStream(IID_IE2,ptr,&pStm);
- assert(SUCCEEDED(hr));
- HANDLE hThread=CreateThread(NULL,size_t(),f,NULL,DWORD(),NULL);
- WaitForSingleObject(hThread,INFINITE);
- ptr.Release();
- }
- };
- IStream* WriteMarshalToMemory::pStm = NULL;
- IStream* g_pStm;
- DWORD WINAPI tf(void*)
- {
- CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
- IMy1Ptr pGet;
- HRESULT hr=CoGetInterfaceAndReleaseStream(g_pStm,IID_IMy1,(LPVOID*)&pGet);
- assert(SUCCEEDED(hr));
- long ret=pGet->Add(44,29);
- cout<<ret<<endl;
- CoUninitialize();
- return 0;
- }
- void TestMarshal()
- {
- CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
- IMy1Ptr ptr(CLSID_My1,NULL,CLSCTX_ALL);
- assert(ptr);
- HRESULT hr = CoMarshalInterThreadInterfaceInStream(IID_IMy1,ptr,&g_pStm);
- assert(SUCCEEDED(hr));
- HANDLE hThread=CreateThread(NULL,0,tf,NULL,0,NULL);
- Sleep(10000);//子线程调用STA主线程创建的com对象,需要用到主线程的消息队列
- MessageBox(0, _T(""), _T(""), 0);//MessageBox显示的时候创建消息队列,点击OK的时候关闭消息队列
- WaitForSingleObject(hThread,INFINITE);
- ptr.Release();
- CoUninitialize();
- }
- void UseMyStruct()
- {
- IE3Ptr ptr(CLSID_E3,NULL,CLSCTX_ALL);
- My obj={2,"xyz"};
- ptr->SetMy(&obj);
- MyStruct ms={1,2};
- ptr->SetMyStruct(&ms);
- ptr->GetMy(&obj);
- cout<<obj.m_i<<obj.m_str<<endl;
- ptr.Release();
- }
- void UseClassFactory()
- {
- IClassFactory *pFactory=nullptr;
- HRESULT hr=CoGetClassObject(CLSID_My1,CLSCTX_ALL,NULL,IID_IClassFactory,(void**)&pFactory);
- IMy1* pMy1=nullptr;
- hr=pFactory->CreateInstance(NULL,IID_IMy1,(void**)&pMy1);
- cout<<pMy1->Add(3,3)<<endl;
- pMy1->Release();
- pFactory->Release();
- }
点击(此处)折叠或打开
- int main(void)
- {
- VARIANT var,var2;
- VariantInit(&var);
- VariantInit(&var2);
- V_VT(&var)=VT_I4;
- V_I4(&var)=20;
- VariantChangeType(&var2,&var,VARIANT_NOVALUEPROP,VT_BSTR);
- _tprintf(var2.bstrVal);
- VariantClear(&var);
- VariantClear(&var2);
- CoInitialize(NULL);
- IClassFactory* pf=NULL;
- HRESULT hr=CoGetClassObject(CLSID_Bar,CLSCTX_ALL,NULL,IID_IClassFactory,(void**)&pf);
- IBar* pBar=NULL;
- hr=pf->CreateInstance(NULL,IID_IBar,(void**)&pBar);
- if(pBar)pBar->Release();
- pf->Release();
- IClassFactory2* pf2=NULL;
- hr=CoGetClassObject(CLSID_Bar,CLSCTX_ALL,NULL,IID_IClassFactory2,(void**)&pf2);
- IBar* pBar2=NULL;
- BSTR bstrKey;
- hr=pf2->RequestLicKey(DWORD(),&bstrKey);
- hr=pf2->CreateInstanceLic(NULL,NULL,IID_IBar,bstrKey,(void**)&pBar2);
- if(pBar2)pBar2->Release();
- pf2->Release();
- CoUninitialize();
- return 0;
- }