AutoCAD 3DMAX C语言 Pro/E UG JAVA编程 PHP编程 Maya动画 Matlab应用 Android
Photoshop Word Excel flash VB编程 VC编程 Coreldraw SolidWorks A Designer Unity3D
 首页 > VC编程

组件对象模型的规则

51自学网 2015-08-30 http://www.wanshiok.com

 

以下的代码段阐明了使用嵌套类来实现集合对象接口的范例:
// CSomeObject is an aggregatable object that implements
// IUnknown and ISomeInterface
class CSomeObject : public IUnknown
{
private:
DWORD m_cRef;// Object reference count
IUnknown* m_pUnkOuter; //Outer unknown, no AddRef
// Nested class to implement the ISomeInterface interface
class CImpSomeInterface: public ISomeInterface
{
friend class CSomeObject ;
private:
private:DWORD m_cRef; //Interface ref-count, for debugging
private:IUnknown*m_pUnkOuter; // Outerunknown, for delegation
private:public:
private:CImpSomeInterface() { m_cRef = 0; };
private:~ CImpSomeInterface(void) {};
private:// IUnknown members delegate to the outer unknown
private:// IUnknown members do not control lifetime of object
private:STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
private:{ return m_pUnkOuter->QueryInterface(riid,ppv);};
private:STDMETHODIMP_(DWORD) AddRef(void)
private:{ return m_pUnkOuter->AddRef(); };
private:STDMETHODIMP_(DWORD) Release(void)
private:{ return m_pUnkOuter->Release();};
private:// ISomeInterface members
private:STDMETHODIMP SomeMethod(void)
private:{ return S_OK; };
private:} ;
private:CImpSomeInterface m_ImpSomeInterface ;
private:public:
private:CSomeObject(IUnknown * pUnkOuter)
{
m_cRef=0;
// No AddRef necessary if non-NULL as we're aggregated.
m_pUnkOuter=pUnkOuter;
m_ImpSomeInterface.m_pUnkOuter=pUnkOuter;
} ;
// Static member function for creating new instances (don't use
// new directly).Protects against outer objects asking for interfaces
// other than IUnknown
static HRESULT Create(IUnknown* pUnkOuter, REFIID riid, void **ppv)
{
CSomeObject* pObj;
if (pUnkOuter != NULL && riid != IID_IUnknown)
return CLASS_E_NOAGGREGATION;
pObj = new CSomeObject(pUnkOuter);
if (pObj == NULL)
return E_OUTOFMEMORY;
// Set up the right unknown for delegation (the non-aggregation
case)
if (pUnkOuter == NULL)
pObj->m_pUnkOuter = (IUnknown*)pObj ;
HRESULT hr;
if (FAILED(hr = pObj->QueryInterface(riid, (void**)ppv)))
delete pObj ;
return hr;
}
// Implicit IUnknown members, non-delegating
// Implicit QueryInterface only controls inner object
STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
{
*ppv=NULL;
if (riid == IID_IUnknown)
*ppv=this;
if (riid == IID_ISomeInterface)
*ppv=&m_ImpSomeInterface;
if (NULL==*ppv)
return ResultFromScode(E_NOINTERFACE);
((IUnknown*)*ppv)->AddRef();
return NOERROR;
} ;
STDMETHODIMP_(DWORD)AddRef(void)
{ return++m_cRef; };
STDMETHODIMP_(DWORD)Release(void)
{
if (--m_cRef != 0)
return m_cRef;
delete this;
return 0;
};
};

集合对象

当在一个对象上产生另一个集合对象时,必须遵循以下规则:


当创建一个内部对象时,外部对象必须明确的向Iunknown请求。
外部对象必须保护重入时对破坏代码的人工引用的Release实施。
如果外部对象查询任一内部对象接口,它必须调用自己的未知Release。释放此指针时,外部对象紧随内部对象指针调用自己的外部未知AddRef。
// Obtaining inner object interface pointer
pUnkInner->QueryInterface(IID_IFoo,&pIFoo);
pUnkOuter->Release();
// Releasing inner object interface pointer
pUnkOuter->AddRef();
pIFoo->Release();
外部对象不能盲目地对内部对象的未被识别接口进行查询,除非操作是为外部对象特定目的。

房间线程化模型

房间模型线程化的细节实际上非常简单,但是必须小心地遵循以下规则:
每个对象存在于单线程中(在单独的房间中)。
所有对一对象的调用必须基于自己的线程(在自己的房间中)。直接从别的线程中调用对象是禁止的。试图用空线程方式使用对象的申请,将在操作系统的未来版本中遇上不能正确运行的问题。这条规则的含义就是在房间之间,必须安排对象的所有指针。
为了处理从不同进程或同一进程的不同房间中的调用,在对象中的每一房间/线程必须有一个消息队列。这就意味着线程的工作函数必须有一个GetMessage/DispatchMessage循环。假如在线程之间有别的同步原语用来通信,那么Microsoft Win32的sgWaitForMultipleObjects将被用来等待消息和线程同步事件。
基于DLL或进程内的对象必须在注册表中标记为"房间识别",通过给注册数据库的InprocServer32关键字增添名为"ThreadingModel=Apartment"的变量实现。
房间识别对象应仔细填写DLL表项。对房间识别对象调用CoCreateInstance的每一个房间将从它的线程调用DllGetClassObject。故DllGetClassObject应能多级类对象或单线程安全对象。从任一线程调用CoFreeUnusedLibraries,都通过主房间线程来调用DllCanUnloadNow.。

 
 
说明
:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。

上一篇:VC+DirectShow对视频进行图片处理之五  下一篇:VC 和 MFC 的一些常见问题