Com组件从OLE技术上发展而来:
Object Linking and Embedding,对象连接与嵌入,简称OLE技术。OLE 不仅是桌面应用程序集成,而且还定义和实现了一种允许应用程序作为软件“对象”(数据集合和操作数据的函数)彼此进行“连接”的机制,这种连接机制和协议称为组件对象模型(COM)。
COM是一种规范而不是实现,是一种面向对象的编程标准(Component ObjectModule)在c++中COM实际就为c++类,用它来实现接口进行操作。
COM对于编程语言的唯一要求是必须能够创建结构指针,并可以通过指针调用函数。COM对象通过一组或多组相关函数来访问对象中的数据,这些数据集合称为接口。
接口是一个纯虚函数的定义,不能直接创建实体,每个接口都有一个全局唯一的GUID值,可以通过这个值访问接口。
所有的接口都是从一个核心接口IUnknown派生而来,IUnknown接口包含了三个重要的方法:QueryInterface、AddRef、Release。
QueryInterface用于说明这个组件是否支持特定接口,如果支持返回接口的指针,不支持返回一个空指针。
AddRef和Release实现对COM的内存引用 的计数。当对COM第一个调用AddRef时,COM被调入内存;当调用Release,最后释放COM时,COM会从内存释放。
COM组件在使用前应该进行注册,它的一些信息随着COM组件的注册被写入到注册表中,反注册就是把组件的注册信息从注册表中删除。Windows系统中使用 RegSvr32.exe对COM组件进行注册和反注册,RegSvr32.exe调用COM组件的DllRegisterServer注册,调用DllUnRegisterServer进行反注册。如com.dll为一个组件,则控制台注册:
RegSvr32 com.dll
反注册:
RegSvr32 –ucom.dll
COM组件的规则:
1、 实现IUnknown规则。Com组件必须实现IUnknown接口。
2、 内存管理规则。管理内存即管理指针,接口指针的寿命管理通过调用每个com接口中的AddRef()和Release()两种方法来实现。
3、 引用计数规则。 引用程序通过计数跟踪COM实例,保证符合COM规范。
Com组件的设计
VS中使用ATL方便设计组件。
ATL,Active Template Library活动模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。通过活动模板库,可以建立COM组件,然后通过ASP页面中的脚本对COM对象进行调用。这种COM组件可以包含属性页、对话框等等控件。
COM组件的调用之 工厂化方法调用接口
工厂化函数
STDAPI CoGetClassObject
(
REFCLSIDrclsid, //组件的CLSID值
WORDdwClsContext, //组件类别
COSERVERINFO*pServerInfo, //服务器信息,默认为NULL
REFIIDriid, //工厂方法标识符
LPVOID*ppv, //COM组件工厂指针
)
调用了CoGetClassObject之后得到了IClassFactory接口指针,使用IClassFactory接口调用CreateInstance得到调用的指针接口。
HRESULT CreateInstance
( IUnknown*pUnkOuter, //指向UnKnown接口,与CoCreateInstance相同
REFIIDriid, //调用接口标识符
Void** ppvObject //接口指针
)
示例:
myCom组件含有IGetRes接口,该接口含有Hello()方法,IGetResEx接口,该接口还含有HelloEx()方法,使用工厂化方法调用COM接口方法。
CoInitialize(NULL);
HRESULT hr;
CLSID clsid;
//得到myCom组件IGetRes接口指针的CLSID号
hr = CLSIDFromProgID(OLESTR(“myCom.GetRes”),&clsid);
//首先说明i一个IGetRes接口、IGetResEx接口和类工厂接口
IGetRes* ptr;
IGetResEx* ptrEx;
IClassFactory* p_Classfactory;
//首先需要得到COM 对象工厂(IClassFactory)指针
hr = GoGetClassObject(clsid, CLSCTX_INPROC_SERVER,NULL, IID_IClassFactory, (LPVOID*) &p_Classfactory);
//使用工厂化的方法得到IGetRes接口指针
P_classfactory->CreateInstance(NULL,__uuidof(IGetRes), (LPVOID*) &ptr);
//使用工厂化的方法得到IGetResEx接口指针
P_Classfactory->CreateInstance(NULL,__uuidof(IGetResEx), (LPVOID*)&ptrEX);
//调用IGetRes接口的Hello函数
Ptr->Hello();
//调用IGetResEx接口的HelloEx()函数
ptrEx->HelloEx();
CoUninitialize();
Com组件使用API调用接口函数
STDAPI CoCreateInstance
( REFCLSID rclsid, //组件的CLSID值
LPUNKNOWNpUnkOuter, //指向UnKnown接口
DWORDdwClsContext, //组件类别
REFIIDriid, //调用接口标识符
LPVOID*ppv, //接口指针
)
pUnkOuter 如果为NULL, 表明此对象不是聚合式对象的一部分。如果不是NULL,则指针指向一个聚合式对象的IUnKnown接口
dwClsContext 参数一般设置为CLSCTX_INPROC_SERVER
riid 是接口的GUID值,可以通过以下函数得到:
__uuidof(expression)
uuidof 得到指向expression的GUID值。
使用API 调用接口IGetRes的方法Hello()的实例:
CoInitialize(NULL);
CLSID clsid;
//得到myCom组件IGetRes接口指针的CLSID号
HRESULT hr = CLSIDFromProgID(OLESTR(“myCom.GetRes”),&clsid);
IGetRes *ptr;
//得到接口IGetRes的指针
hr = CoCreateInstance(clsid, NULL,CLSCTX_INPROC_SERVER, __uuidof(IGetRes), (LPVOID*) &ptr);
//调用IGetRes接口的Hello()函数
Ptr->Hello();
CoUninitialize();