ATL7中OBJECT_ENTRY_AUTO宏是如何实现com对象映射表
来源:互联网 发布:c语言入门材料 编辑:程序博客网 时间:2024/06/08 06:49
在ATL3.0中,是通过对象映射表来注册服务器。 BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_MyCircleCollectionCreator, CMyCircleCollectionCreator)
END_OBJECT_MAP( )
当ATL注册服务器时,最终调用到AtlModuleRegisterServer函数进行服务器注册。对于组件支持的所有对象,它创建一个注册表项进行注册,注册过程结束。
但是,在ATL7中,以上三个宏都已经过时,取而代之的是宏OBJECT_ENTRY_AUTO。下面我们就来分析宏OBJECT_ENTRY_AUTO的实现。
二、宏OBJECT_ENTRY_AUTO的定义。
1. 我们首先看看_ATL_OBJMAP_ENTRY的定义:
struct _ATL_OBJMAP_ENTRY30
{
const CLSID* pclsid;
HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister);
_ATL_CREATORFUNC* pfnGetClassObject;
_ATL_CREATORFUNC* pfnCreateInstance;
IUnknown* pCF;
DWORD dwRegister;
_ATL_DESCRIPTIONFUNC* pfnGetObjectDescription;
_ATL_CATMAPFUNC* pfnGetCategoryMap;
};
typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY;
2. 宏OBJECT_ENTRY_AUTO的定义如下:
#define OBJECT_ENTRY_AUTO(clsid, class)
__declspec(selectany) ATL::_ATL_OBJMAP_ENTRY __objMap_##class = /
{ /
&clsid,/
class::UpdateRegistry,/
class::_ClassFactoryCreatorClass::CreateInstance,/
class::_CreatorClass::CreateInstance, /
NULL, /
0, /
class::GetObjectDescription, /
class::GetCategoryMap,
class::ObjectMain };/
/
extern "C" __declspec(allocate("ATL$__m")) /
__declspec(selectany) ATL::_ATL_OBJMAP_ENTRY * const __pobjMap_##class /
= &__objMap_##class; /
OBJECT_ENTRY_PRAGMA(class)
3. 接下来我们看一个辅助的宏OBJECT_ENTRY_PRAGMA,它的定义如下:
#define OBJECT_ENTRY_PRAGMA(class) /
__pragma(comment(linker, "/include:___pobjMap_" #class));
三、宏OBJECT_ENTRY_AUTO的功能
1. 结构体_ATL_OBJMAP_ENTRY就不用多说了,和ATL3是完全一样的。
2. 宏OBJECT_ENTRY_AUTO的功能:
1) 使用clsid, class的信息,生成_ATL_OBJMAP_ENTRY的一个实例,变量名为__objMap_加上class的实际值。
2) 声明1)所生成实例的一个指针,并赋值为1)生成的实例的地址。但是指针被放在ATL$_m段中。
3. 宏OBJECT_ENTRY_PRAGMA的功能是告诉连接器向符号表中添加符号___objMap_加上class的实际值。注:在X86平台下,符号名为声明的名字前加下划线。所以在OBJECT_ENTRY_PRAGMA宏中,pobjMap之前有三个下划线。
四、在哪部分代码中使用OBJECT_ENTRY_AUTO
创建ATL7.0工程时:
1. 如果使用的是非属性化编程,那么它在COM类的头文件中,它由向导自动生成,千万不要删除该宏,否则将不能够创建该类的实例。 而这样的错误又是非常难发现的。
2. 如果使用的是属性化编程,那么在COM类的前面有coclass属性,编译器将向代码中插入一些代码完成以下功能:
l 添加COM类的基类
l 产生注册代码
l 产生接口映射表
l 产生对象映射项,即宏OBJECT_ENTRY_AUTO
所以在代码中,你实际看不到OBJECT_ENTRY_AUTO。
五、OBJECT_ENTRY_AUTO和系统其他部分的协作,这里分析对象映射表的建立及使用。
如果使用非属性化编程,那么用户可以生成任意合法COM类名称;如果使用属性化编程,我们根本不知道_ATL_OBJMAP_ENTRY指针变量的名字,这些对于ATL库来讲,它不可能预先知道用户定义的COM类的名字。那么它是如何遍历对象映射表,来进行更新注册表呢?
答案在于对象映射表的建立,我们先来看映射表的开始项、结束项。他们的定义如下:
__declspec(selectany) __declspec(allocate("ATL$__a")) _ATL_OBJMAP_ENTRY* __pobjMapEntryFirst = NULL;
__declspec(selectany) __declspec(allocate("ATL$__z")) _ATL_OBJMAP_ENTRY* __pobjMapEntryLast = NULL;
分析如下:
l 需要注意的是,__pobjMapEntryFirst、__pobjMapEntryLast分别被放置在段ATL$_a和ATL$_z中。
l 再次需要注意的是,通过宏OBJECT_ENTRY_AUTO放置的变量在ATL$_m中。
l 当连接器布局代码时,它按根据的名称,按照字母排序的规则,排列所有段。这样在段ATL$_a中的变量出现在段ATL$_z所有变量之前。
l 最后使用#pragma comment(linker, "/merge:ATL=.rdata"),将三个段中的所有数据合并到段.rdata只读数据段中。
l 最后形成的布局可能如下:
__pobjMapEntryFirst
…
UserDefinedPtr1
UserDefinedPtr2
…
__pobjMapEntryLast
通过这种方式,就形成了对象映射表。而在ATL库中,可以根据__pobjMapEntryFirst、__pobjMapEntryLast来定位对象映射表,对其中的所有对象进行注册。
http://blog.csdn.net/terryc007/article/details/2601982
- ATL7中OBJECT_ENTRY_AUTO宏是如何实现com对象映射表
- ATL7中OBJECT_ENTRY_AUTO宏是如何实现com对象映射表
- OBJECT_ENTRY_AUTO
- COM组件对象如何实现索引属性
- 如何判断两个COM指针是同一个对象
- NHibernate如何实现对象与数据库之间的映射
- COM接口映射表 .
- COM接口映射表
- C#实现对象映射
- .NET程序中如何清除Excel的COM对象
- [QTP] vbscript中如何引用一个COM对象
- 如何实现映射
- Struts2中是如何实现include文件
- java对象如何映射clob
- ATL是通过接口映射表来实现QueryInterface
- 垃圾回收机制中,引入计数是如何实现的,内部原理是什么,怎么维持对象引用的
- 关于面向对象思想中二维数组如何与对象映射思路的思考
- 【JAVA】Java是如何实现面向对象的?
- Android有效解决加载大图片时内存溢出的问题
- linux shell 将上一个命令的输出作为下一个命令的参数
- android.view.WindowManager$BadTokenException: Unable to add window
- 词权重计算及应用
- 设计模式6大原则之迪米特法则(Law Of Demeter)
- ATL7中OBJECT_ENTRY_AUTO宏是如何实现com对象映射表
- Mac OS X的剪切操作
- ext4 grid 分页前台后台源码
- JSch - Java实现的SFTP(文件下载详解篇
- C/C++浮点数在内存中的存储方式
- hdu 4617
- 条件判断 & 循环语句的逆向
- KMP算法
- NSDate显示和时区的关系