一、
在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
;
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 = /
;/ /
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(***ment(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.
如果使用的是非屬性化程式設計,那麼它在
***類的標頭檔案中,它由嚮導自動生成,千萬不要刪除該巨集,否則將不能夠建立該類的例項。 而這樣的錯誤又是非常難發現的。 2.
如果使用的是屬性化程式設計,那麼在
***類的前面有
coclass
屬性,編譯器將向**中插入一些**完成以下功能: l
新增***
類的基類 l
產生註冊** l
產生介面對映表 l
產生物件對映項,即巨集
object_entry_auto
所以在**中,你實際看不到
object_entry_auto。
五、object_entry_auto
和系統其他部分的協作,這裡分析物件對映表的建立及使用。
如果使用非屬性化程式設計,那麼使用者可以生成任意合法
***類名稱;如果使用屬性化程式設計,我們根本不知道
_atl_objmap_entry
指標變數的名字,這些對於
atl庫來講,它不可能預先知道使用者定義的
***類的名字。那麼它是如何遍歷物件對映表,來進行更新登錄檔呢?
答案在於物件對映表的建立,我們先來看對映表的開始項、結束項。他們的定義如下:
__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 ***ment(linker, "/merge:atl=.rdata")
,將三個段中的所有資料合併到段
.rdata
唯讀資料段中。 l
最後形成的布局可能如下:
__pobjmapentryfirst …
userdefinedptr1
userdefinedptr2 …
__pobjmapentrylast
通過這種方式,就形成了物件對映表。而在
atl庫中,可以根據
__pobjmapentryfirst
、__pobjmapentrylast
來定位物件對映表,對其中的所有物件進行註冊。
關於專用和共享伺服器程序
oracle資料庫建立伺服器程序來處理連線到例項的使用者程序的請求。伺服器程序可以是以下任一種 您的資料庫始終啟用以允許專用的伺服器程序,但您必須通過設定乙個或多個初始化引數來專門配置和啟用共享伺服器。專用伺服器程序 圖5 1 oracle資料庫專用伺服器程序 說明了專用伺服器程序如何工作。在該圖中...
Sipdroid中像伺服器註冊是如何實現的 一
關於 sipdroid是如何實現像伺服器註冊的 首先告訴大家 塊在 註冊的核心在registeragent類中的函式register int time 中,註冊的核心是 create message re modified by mandrajg message req messagefactory...
一種併發伺服器關於程序的問題
在學習 的時候曾經發生過這種問題 一台 機,執行虛擬機器,一台 嵌入式裝置 掛在 在 上面。在 執行伺服器程式 在 執行客戶端程式 與伺服器連線。伺服器是併發的,連線以後它產生 個子程序如下 root localhost echo ps a pid tty time cmd 1514 pts 0 0...