时间: 14:09 2010-8-19
PAGE:
http://www.codeguru.com/Cpp/COM-Tech/activex/tutorials/article.php/c5567
http://www.codeproject.com/KB/COM/comintro.aspx
感言: COM 很00,很设计模式
COM :
其的接口分离:操作列表
实现:
实现类:
其要求实现接口类,与一些常用的接口.
其是可以通过接口类继承一些接口,然后在实现类当中统一实现。
(SWE是就是这样处理的,如自定义控件,我们能否子类化内置控件呢, 不知道,主要是:内置控件其提供了接口
类,但其没有提供实现类,自定义控件其就提供了相关实现类。
COM 很00,很设计模式: 内置控件其提供了接口,我们能否使用:装饰者模式来添加新功能(如果对于修改控件的
外观,其能够在XAML文件当中实现,但用C++我们还很好的实现,思考。。。)
实现类其一般继承接口类(自定义的)与接口类当中的接口的对应实现类。
如:
interface I a : public Ib
{};
class a : public Ia, b
{
}
COM 的内部类,其是由a 创建。
a 其是由一个工厂函数来创建的。(这种设计思想在MS的SWE当中到处可见)
整个COM 其是放在一个DLL文件当中,
一个DLL文件当中其可以包含多个COM.
DLL 文件当中其就有一个工厂函数.
其一定要创建一个COM CLASS.
然后通过COM CLASS::QueryInterface(IID,PPV) 来查找接口.
QueryInterface其是用来打查找接口的,当要查找接口的时候其就可以使用QueryInterface。
使用COM之前要创建COM对象与查找接口 ,其调用一个工厂函数就能一同实现.
在一个标准的COM,其是有一个IFactoryClass instance ( 工厂类), 注意工厂类其是用于创建其他对象(COM
CLASS),而不是自身对象,
然后COM CLASS 其就可以查找接口.
如
HRESULT __stdcall CAddFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv)
{
// Create an instance of the component.
CAddObj* pObject = new CAddObj ;
if (pObject == NULL)
{
return E_OUTOFMEMORY ;
}
// Get the requested interface.
return pObject->QueryInterface(iid, ppv) ;
}
CLIENT 通过CreateInstance(工厂函数)传入IID,就可以查找到接口。
在SWE当中,其就是以这种思路进行的实现。
其首先要求控件进行注册,==》 建立一个表。
CAddObj * pObject = new CAddObj;
这一步在SWE当中是怎么样实现的.分为两步:
1. new
2.Create ( 因为要LOAD XAML ,查找控件的成员,与对于控件相关成员绑定事件)
最后才是查找接口. 注意其没有使用NEW 而是使用类型转换.
HRESULT __stdcall CAddObj::QueryInterface(
REFIID riid ,
void **ppObj)
{
if (riid == IID_IUnknown)
{
*ppObj = static_cast<IAdd*>(this) ;
AddRef() ;
return S_OK;
}
if (riid == IID_IAdd)
{
*ppObj = static_cast<IAdd*>(this) ;
AddRef() ;
return S_OK;
}
if (riid == IID_IFileIO)
{
*ppObj = static_cast<IFileIO*>(this) ;
AddRef() ;
return S_OK;
}
//
//if control reaches here then , let the client know that
//we do not satisfy the required interface
//
*ppObj = NULL ;
return E_NOINTERFACE ;
}
我们存储控件,
我们应该存储哪一个部分呢。是实现类,还是接口
思考:
1.
其为什么只是接口有IID,
而实现类没有IID,( 其对应于CLSID,好像可以有,也可以没有,所以在XAML2CPP.EXE所生成的代码当中,其没有
写)
2.其为什么没有采用这种方式呢,这种形式是什么.
hr = CoCreateInstance ( CLSID_XXX, // CLSID of coclass
NULL, // not used - aggregation
CLSCTX_INPROC_SERVER, // type of server
IID_IXXXX, // IID of interface
(void**) &pIXX ); // Pointer to our interface pointer
DllGetClassObject ==> 其是在DLL当中有IClassFactory.
CoCreateInstance 其是DLL当中没有IClassFactory的情形,其直接完成IClassFactory的功能.
STDAPI DllGetClassObject(const CLSID& clsid,
const IID& iid,
void** ppv)
{
//
//Check if the requested COM object is implemented in this DLL
//There can be more than 1 COM object implemented in a DLL
//
if (clsid == CLSID_AddObject)
{
//
//iid specifies the requested interface for the factory object
//The client can request for IUnknown, IClassFactory,
//IClassFactory2
//
CAddFactory *pAddFact = new CAddFactory;
if (pAddFact == NULL)
return E_OUTOFMEMORY;
else
{
return pAddFact->QueryInterface(iid , ppv);
}
}
//
//if control reaches here then that implies that the object
//specified by the user is not implemented in this DLL
//
return CLASS_E_CLASSNOTAVAILABLE;
}
// 在DLLMAIN.CPP 当中,
其传入CLSID 是CLSID_AddObject,而不是CLSID_FactoryObject,( 因为IFactoryObject 其只是一个接口,而非
实现类)
但其创建的对象:CAddFactory *pAddFact = new CAddFactory;
其的接口IID:IID_IClassFactory OR IID_IUnknown.
PPV: 其是指向 CAddFactory 而不是CAddObject.
==》 以后要调用COM的接口,其要使用调用 CAddFactory::CreateInstance
然后调用CAddObj::QueryInterface.
a class ID ,or CLSID ,is a GUID that names a coclass(short for component object class). an interface ID,or
IID,is a GUID that names an interface.
A COM object is an instance of a coclass in memory
Note that a COM "class" is not the same as a c++ "class"
a COM class 是由A C++ CLASS 实现的。
在程序当中怎么样使用了,使用哪一个 class呢,
如存储
Create A COM OBJECT ,其就是创建一个C++ OBJECT 吗,
将C++ OBJECT 赋值给INTERFACE,其就是INTERFACE 类了吗
every COM interface is derived from IUnkown.
every COM object(C++ 对象) implements IUnkown.
QueryInterface() - Requests an interface pointer from a COM object .You use this when a coclass
implement more than one interface.
一个COM class 其是一个实现了所有接口的C++ CLASS 吗,
一个COM CLASS 其是否允许有多个C++ CLASS呢.
COM 其是采用了很多的设计模式,
面向接口编程,
其之所以能够很自然的这样处理是因为,其采用了接口,这是使用很多设计模式的基础.( 如装饰,适配器)
其当中之所以要引用smartpointer,其就是为了管理new出来的对象,由谁业delete的问题.
smartpointer : smart,pointer.
用户将其当作pointer来进行处理。
smart: 其是用于管理pointer的指针引用 。
对于接口类的使用,其是通过
SmartPointer