__declspec(allocate("segname"))和__declspec( selectany )(AC1)
AC1,由VS2005的ATL嚮導生成的預設COM物件程式碼分析ATL如何實現COM,第一部分。
為了多多研習ATL想到生成的程式碼,visio、rose、word、excel加上我的筆本全上陣,終於把各個模板類混了個瞭解、跟巨集混了個臉熟。當我藉助偵錯程式想把一個classfactory和com物件的由來看個明白的時候,我發現疑惑很多。不過好在簡單看出了點門道,但要說清楚,非三言兩語可以完成,只好寫個系列以AC1、AC2、ACn等標識。
__declspec(allocate("segname")) 告訴編譯器分配一個名字為segname的段,譬如:
__declspec(allocate("LIUAN")) int myValue = 100;
告訴編譯器,分配一個叫LIUAN的段,把我們的變數myValue存放在那裡,另一種說法是向符號表裡新增myValue符號,使用了這個手段的專案在編譯出來的map檔案裡,可以明顯的發現類似這樣
Start Length Name Class
0006:00000000 00000104H LIUAN DATA
的東西,實際地址可能有差別,但是名字不會變。我們要求編譯器加入新的符號,它做到了。
在實際使用時,還需要#pragma section事先告訴編譯器,我們要使用的段名,完整的示例是這樣的:
#pragma section("LIUAN", read) __declspec(allocate("LIUAN")) int myValue = 100; int _tmain(int argc, _TCHAR* argv[]) { printf("%d/n",myValue); return 0; }
Start Length Name Class
0005:000002fc 00000545H .idata$6 DATA
0006:00000000 00000104H LIUAN DATA //this line
0007:00000000 00000169H .rsrc$01 DATA
__declspec(selectany)告訴編譯器我要使用pick-any COMDAT,說白了就是跟編譯器說我要在標頭檔案裡初始化東西。在標頭檔案裡初始化整形資料可以藉助enum來模擬實現,但是初始化其他資料就比較難了,selectany給我們提供了一個方式。
//someheader.h
#pragma section("LIUAN", read)
extern "C" __declspec(allocate("LIUAN")) __declspec(selectany) int myValue = 100;
__pragma(comment(linker, "/include:_myValue"))
對於ATL生成的預設com物件,我們開啟map檔案發現有:
0003:0000a344 00000104H LIUAN DATA
對於ATL生成的預設com物件,我們開啟map檔案發現有
0003:0000a344 00000104H ATL __a DATA 0003:0000a448 00000104H ATL __m DATA 0003:0000a54c 00000104H ATL __z DATA
是的,這三個變數就是使用了這種手段寫進去的。