ATL库的使用
1 ATL(Active Template Library)库
是一个模板库,封装了COM SDK相关细节,以及接口和组件实现的相关的机制
2 ATL接口的相关类
内部封装了IUnknown接口
2.1 CComObjectRootBase模板类
封装了引用计数,以及内部接口函数等相关的内部调用函数
2.2 CComObjectRootEx
父类是CComObjectRootBase,是一个模板类,封装了对引用计
数的增加和减少函数
2.3 CComSingleThreadModel
实现了对引用计数的++和--操作(用于单线程)
2.4 CComMultiThreadModel
实现了对引用计数的原子锁的++和——操作(用于多线程)
2.5 CComObject 模板类
实现了组件、IUnknown接口的函数,提供了组件创建函数
CComSingleThreadModel和CComMultiThreadModel作为模板参数构造CComObjectRootEx对象
3 使用ATL编写组件
#include "atlbase.h" //必须在前面
#include "atlcom.h"
3.1 IDL定义接口 必须import "objidl.idl";
3.2 增加ATL库的头文件
#include "atlbase.h"
#include "atlcom.h"
3.3 添加组件的实现类,并且继承CComObjectRootEx和IMath接口
3.4 添加接口查询宏
BEGIN_COM_MAP(CMath)
COM_INTERFACE_ENTRY(IMath)
END_COM_MAP()
3.5 添加和实现IMath接口的函数
IUnknown* pIUnknown = NULL;
CComObject<CMath>* pMath = NULL;
CComObject<CMath>::CreateInstance(&pMath);
pMath->QueryInterface(IID_IUnknown, (LPVOID*)&pIUnknown);
return pIUnknown;
3.3 导出接口
4 代码过程
4.1 CComObject<CMath>;实际是基于组件CMath派生子CComObject,
例如 class CComObject:public CMath
在CComObject类当中实现了IUnknown接口的3个函数,
4.2 在CComObject中AddRdf和Release函数分别调用CMath的父类
CComObjectRootEx提供的InternalAddRef/InternalRelease实现引用计
数的加减
4.3 在InternalAddRef/InternalRelease中会调用CComObjectRootEx的
模板参数所提供的加减函数完成引用计数的加减
模板参数
CComSingleThreadModel
CComMultiThreadModel
例如 CComObjectRootEx<CComMultiThreadMOdel>
{
InternalAddRef()
{
CComMultiThreadModel::InCreme
}
}
4.4 在CComObject中QueryInterace函数会调用CMath::_InternalQueryInterace,
4.5 CMath::_InternalQueryInterace是通过BEGIN_COM_MAP/END_COM_MAP添加,并且内部调用了父类CComObjectRootBase提供的InternalQueryInterace函数
代码示例:
comobj.idl
import "oaidl.idl";
import "ocidl.idl";
import "objidl.idl";
[
object,
uuid(033F167D-6FFD-47EC-A450-34A3E45E55CE)
]
interface IMath :IUnknown
{
HRESULT Add(long nAdd1, long nAdd2, long* pnAdd) = 0;
HRESULT Sub(long nSub1, long nSub2, long* pnSub) = 0;
};
[
uuid(77B18693-AE5A-409D-9C01-5FEAE163153D)
]
coclass ComObj
{
interface IMath;
};
Math.h
#pragma once
//ATL库头文件
#include "atlbase.h"
#include "atlcom.h"
#include "comobj_h.h"
extern const CLSID CLSID_Math;
class CMath :public CComObjectRootEx<CComMultiThreadModel>,
public IMath,
public CComCoClass<CMath, &CLSID_Math>
{
public:
CMath();
~CMath();
public:
//用于接口查询等相关信息的宏
BEGIN_COM_MAP(CMath)
COM_INTERFACE_ENTRY(IMath)
END_COM_MAP()
//IMath接口的函数
public:
STDMETHOD(Add)(long nAdd1, long nAdd2, long* pnAdd);
STDMETHOD(Sub)(long nSub1, long nSub2, long* pnSub);
};
Math.cpp
#include "stdafx.h"
#include "Math.h"
CMath::CMath()
{
}
CMath::~CMath()
{
}
STDMETHODIMP CMath::Add(long nAdd1,
long nAdd2,
long* pnAdd)
{
*pnAdd = nAdd1 + nAdd2;
return S_OK;
}
STDMETHODIMP CMath::Sub(long nSub1,
long nSub2,
long* pnSub)
{
*pnSub = nSub1 - nSub2;
return S_OK;
}
组件创建函数
IUnknown* MyCreateInstance()
{
IUnknown* piUnknown = NULL;
//定义组件对象的指针
CComObject<CMath>* pMath = NULL;
//创建组件对象
CComObject<CMath>::CreateInstance(&pMath);
//获取IUnknown接口
pMath->QueryInterface(IID_IUnknown,
(LPVOID*)&piUnknown);
return piUnknown;
}