青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-250  評論-20  文章-55  trackbacks-0

一、前言

  上兩回中,咱們用 ATL 寫了第一個 COM 組件程序,這回中,主要介紹編譯、注冊和調用方法。示例程序你已經下載了嗎?如果還沒有下載,vc6.0 的用戶點這里,vc.net 的用戶點這里。


二、關于編譯

  2-1 最小依賴

  “最小依賴”,表示編譯器會把 ATL 中必須使用的一些函數靜態連接到目標程序中。這樣目標文件尺寸會稍大,但獨立性更強,安裝方便;反之系統執行的時候需要有 ATL.DLL 文件的支持。如何選擇設置為“最小依賴”呢?答案是:刪除預定義宏“_ATL_DLL”,操作方法見圖一、圖二。


圖一、在vc6.0中,設置方法


圖二、在 vc.net 2003中,設置方法

  2-2 CRT庫
  如果在 ATL 組件程序中調用了 CRT 的運行時刻庫函數,比如開平方 sqrt() ,那么編譯的時候可能會報錯“error LNK2001: unresolved external symbol _main”。怎么辦?刪除預定義宏“_ATL_MIN_CRT”!操作方法也見圖一、圖二。(vc.net 2003 中的這個項目屬性叫“在 ATL 中最小使用 CRT”)

  2-3 MBCS/UNICODE
  這個不多說了,在預定義宏中,分別使用 _MBCS 或 _UNICODE。

  2-4 IDL 的編譯
  COM 在設計初期,就定了一個目標:要能實現跨語言的調用。既然是跨語言的,那么組件的接口描述就必須在任何語言環境中都要能夠認識。怎么辦?用 .h 文件描述?------ C語言程序員笑了,真方便!BASIC 程序員哭了:-( 因此,微軟使用了一個新的文件格式---IDL文件(接口定義描述語言)。IDL 是一個文本文件,它的語言語法比較簡單,很象C。具體 IDL 文件的講解,見下一回《COM 組件設計與應用(八)之添加新接口》。IDL 經過編譯,生成二進制的等價類型庫文件 TLB 提供給其它語言來使用。圖三示意了 ATL COM 程序編譯的過程:


圖三、ATL 組件程序編譯過程

  說明1:編譯后,類型庫以 TLB 文件形式單獨存在,同時也保存在目標文件的資源中。因此,我們將來在 #import 引入類型庫的時候,既可以指定 TLB 文件,也可以指定目標文件;
  說明2:我們作為 C/C++ 的程序員,還算是比較幸福的。因為 IDL 編譯后,特意為我們提供了 C 語言形式的接口文件。
  說明3:IDL 編譯后生成代理/存根源程序,有:dlldata.c、xxx_p.c、xxxps.def、xxxps.mak,我們可以用 NMAKE.EXE 再次編譯來產生真正的代理/存根DLL目標文件(注1)。


三、關于注冊

  情況1:當我們使用 ATL 編寫組件程序,注冊不用我們來負責。編譯成功后,IDE 會幫我們自動注冊;
  情況2:當我們使用 MFC 編寫組件程序,由于編譯器不知道你寫的是否是 COM 組件,所以它不會幫我們自動注冊。這個時候,我們可以執行菜單“Tools\Register Control”來注冊。
  情況3:當我們寫一個具有 COM 功能的 EXE 程序時,注冊的方法就是運行一次這個程序;
  情況4:當我們需要使用第三方提供的組件程序時,可以命令行運行“regsvr32.exe 文件名”來注冊。順便說一句,反注冊的方法是“regsvr32.exe /u 文件名”;
  情況5:當我們需要在程序中(比如安裝程序)需要執行注冊,那么:

typedef HRESULT (WINAPI * FREG)();
TCHAR szWorkPath[ MAX_PATH ];

::GetCurrentDirectory( sizeof(szWorkPath), szWorkPath );	// 保存當前進程的工作目錄
::SetCurrentDirectory( 組件目錄 );	// 切換到組件的目錄

HMODULE hDLL = ::LoadLibrary( 組件文件名 );	// 動態裝載組件
if(hDLL)
{
	FREG lpfunc = (FREG)::GetProcAddress( hDLL, _T("DllRegisterServer") );	// 取得注冊函數指針
	// 如果是反注冊,可以取得"DllUnregisterServer"函數指針
	if ( lpfunc )	lpfunc();	// 執行注冊。這里為了簡單,沒有判斷返回值
	::FreeLibrary(hDLL);
}

::SetCurrentDirectory(szWorkPath);	// 切換回原先的進程工作目錄
  上面的示例,在多數情況下可以簡化掉切換工作目錄的代碼部分。但是,如果這個組件在裝載的時候,它需要同時加載一些必須依賴的DLL時,有可能由于它自身程序的 BUG 導致無法正確定位???.....還是讓我們自己寫的程序,來彌補它的錯誤吧......誰讓咱們是好人呢 ,誰讓咱們的水平比他高呢,誰讓咱們在 vckbase 上是個“榜眼”呢......


四、關于組件調用

  總的來說,調用組件程序大概有如下方法:
 
#include 方法IDL編譯后,為方便C/C++程序員的使用,會產生xxx.h和xxx_i.c文件。我們真幸福,直接#include后就可以使用了
#import 方法比較通用的方法,vc 會幫我們產生包裝類,讓我們的調用更方便
加載類型庫包裝類 方法如果組件提供了 IDispatch 接口,用這個方法調用組件是最簡單的啦。不過還沒講IDispatch,只能看以后的文章啦
加載ActiveX包裝類 方法ActiveX 還沒介紹呢,以后再說啦

  下載示例程序后,請逐項瀏覽使用方法:

示例

方法

簡要說明

1#include完全用最基本的 API 方式調用組件,使大家熟悉調用原理
2#include大部分使用 API 方式,使用 CComBSTR 簡化對字符串的使用
3#include展示智能指針 CComPtr<> 的使用方法
4#include展示智能指針 CComPtr<> 和 CComQIPtr<> 混合的使用方法
5#include展示智能指針 CComQIPtr<> 的使用方法
6#include展示智能指針的釋放方法
7#importvc 包裝的智能指針 IxxxPtr、_bstr_t、_variant_t 的使用方法和異常處理
8#importimport 后的命名空間的使用方法

  示例程序中都寫有注釋,請讀者仔細閱讀并同時參考 MSDN 的函數說明。這里,我給大家介紹一下“智能指針”:
  對于操作原始的接口指針是比較麻煩的,需要我們自己控制引用記數、API 調用、異常處理。于是 ATL 提供了2個智能指針的模板包裝類,CComPtr<> 和 CComQIPtr<>,這兩個類都在 <atlbase.h> 中聲明。CComQIPtr<> 包含了 CComPtr<>的所有功能,因此我們可以完全用 CComQIPtr<> 來使用智能接口指針,唯一要說明的一點就是:CComQIPtr<> 由于使用了運算符的重載功能,它會自動幫我們調用QueryInterface()函數,因此 CComQIPtr<> 唯一的缺點就是不能定義 IUnknown * 指針。

    // 智能指針 smart pointer,按照匈牙利命名法,一般以 sp 開頭來表示變量類型
    CComPtr < IUnknown > spUnk;	// 正確
    // 假設 IFun 是一個接口類型
    CComPtr < IFun > spFun;	// 正確
    CComQIPtr < IFun > spFun;	// 正確
    CComQIPtr < IFun, &IID_IFun > spFun;	// 正確
    CComQIPtr < IUnknown > spUnk;	// 錯誤!CComQIPtr不能定義IUnknown指針
給智能指針賦值的方法:
    CComQIPtr < IFun > spFun;	// 調用構造函數,還沒有賦值,被包裝的內部接口指針為 NULL
    
    CComQIPtr < IFun > spFun( pOtherInterface );	// 調用構造函數,內部接口指針賦值為
    // 通過 pOtherInterface 這個普通接口指針調用QueryInterface()得到的IFun接口指針
    
    CComQIPtr < IFun > spFun( spOtherInterface ); // 調用構造函數,內部接口指針賦值為
    // 通過 spOtherInterface 這個只能接口指針調用QueryInterface()得到的IFun接口指針
    
    CComQIPtr < IFun > spFun ( pUnknown );	// 調用構造函數,由IUnknown的QueryInterface()得到IFun接口指針
    
    CComQIPtr < IFun > spFun = pOtherInterface;	// = 運算符重載,含義和上面一樣
    spFun = spOtherInterface;	// 同上
    spFun = pUnknown;	// 同上
    
    pUnknown->QueryInterface( IID_IFun, &sp );	// 也可以通過QueryInterface賦值
    
    // 智能指針賦值后,可以用條件語句判斷是否合法有效
    if ( spFun ){}		// 如果指針有效
    if ( NULL != spFun ){}	// 如果指針有效
    
    if ( !spFun ){}		// 如果指針無效
    if ( NULL == spFun ){}	// 如果指針無效
智能指針調用函數的方法:
    spFun.CoCreateInstance(...);	// 等價與 API 函數::CoCreateInstance(...)
    spFun.QueryInterface(...);	// 等價與 API 函數::QueryInterface()
    
    spFun->Add(...);	// 調用內部接口指針的接口函數

    // 調用內部接口指針的QueryInterface()函數,其實效果和 spFun.QueryInterface(...) 一樣
    spFun->QueryInterface(...);	
    
    spFun.Release();	// 釋放內部的接口指針,同時內部指針賦值為 NULL
    spFun->Release();	// 錯!!!一定不要這么使用。
    // 因為這個調用并不把內部指針清空,那么析構的時候會被再次釋放(釋放了兩次)
咳......不說了,不說了,大家多看書,多看MSND,多看示例程序吧。 寫累了:-(

五、小結

  敬請關注《COM 組件設計與應用(八)》------如何增加 ATL 組件中的第二個接口


注1:編譯代理/存根,vc6.0 中稍微麻煩,我們在后面介紹“進程外組件”和“遠程組件”的時候再介紹。在 vc.net 2003 下則比較簡單,因為代理/存根作為單獨的一個工程項目會自動加到我們的解決方案中了。
posted on 2007-03-12 11:01 jay 閱讀(358) 評論(0)  編輯 收藏 引用 所屬分類: ATL
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美日韩亚洲三区| 久久久久久久高潮| 国产精品黄视频| 欧美肉体xxxx裸体137大胆| 美女成人午夜| 欧美激情一区在线| 欧美另类视频在线| 国产嫩草一区二区三区在线观看| 国产精品www色诱视频| 国产精品乱码久久久久久| 国产免费观看久久黄| 一区三区视频| 一本色道久久综合| 香港成人在线视频| 蜜月aⅴ免费一区二区三区 | 久久爱www| 久久久久一区二区| 亚洲日本一区二区三区| 日韩视频中文| 亚洲女性喷水在线观看一区| 久久久久久国产精品mv| 欧美精品久久一区二区| 国产精品任我爽爆在线播放| 精品不卡视频| 亚洲无线视频| 免费在线亚洲欧美| 亚洲午夜免费福利视频| 蜜臀99久久精品久久久久久软件| 欧美天堂亚洲电影院在线观看| 国产在线不卡视频| 亚洲综合国产| 亚洲人成高清| 久久一区二区视频| 国产精品久久久久久久久久妞妞| 伊人久久婷婷| 久久国产加勒比精品无码| 亚洲国产精品一区在线观看不卡| 性欧美大战久久久久久久免费观看| 美女成人午夜| 影音先锋另类| 久久精品夜色噜噜亚洲a∨| 亚洲精品一区二区在线观看| 久久久久99| 国产在线精品二区| 欧美亚洲日本网站| 一区二区日韩欧美| 欧美日韩午夜在线| 99在线精品视频| 亚洲高清视频一区二区| 一区二区三区 在线观看视| 久久久久一区| 欧美在线999| 国产亚洲二区| 欧美伊人久久久久久午夜久久久久| 在线观看视频一区| 国产精品看片你懂得| 妖精视频成人观看www| 欧美国产日韩亚洲一区| 久久这里只有| 在线看欧美日韩| 麻豆精品网站| 免费观看在线综合| 亚洲国产精品久久人人爱蜜臀| 久久久国产91| 久久噜噜亚洲综合| 亚洲国产精品一区二区www| 欧美超级免费视 在线| 久久手机精品视频| 亚洲茄子视频| 日韩一级大片在线| 国产精品色婷婷久久58| 久久av一区二区三区漫画| 亚洲欧美在线观看| 激情六月婷婷综合| 欧美激情亚洲自拍| 欧美色图首页| 欧美专区福利在线| 久久久免费av| 在线亚洲免费视频| 亚洲一级片在线看| 狠狠狠色丁香婷婷综合久久五月| 另类天堂av| 欧美激情视频一区二区三区免费 | 国产麻豆精品久久一二三| 欧美一区2区视频在线观看| 久久精品99国产精品| 亚洲国产精品一区二区www| 亚洲美女av黄| 国产视频一区免费看| 麻豆av一区二区三区| 欧美日韩网址| 免费不卡亚洲欧美| 国产精品第十页| 欧美成人在线免费视频| 国产精品进线69影院| 免费视频一区| 欧美日韩精品免费观看视频| 久久成人免费日本黄色| 久久久91精品国产一区二区精品| 翔田千里一区二区| 亚洲精品国产拍免费91在线| 一区二区欧美精品| 亚洲三级观看| 欧美在线视频a| 亚洲永久免费视频| 欧美成人午夜激情在线| 久久久久久久久久久一区 | 国产日韩欧美亚洲一区| 欧美国产日韩精品免费观看| 亚洲神马久久| 国产伦精品一区二区三区视频黑人 | 久久国产精彩视频| 免费久久99精品国产| 黑丝一区二区三区| 亚洲欧洲精品成人久久奇米网| 欧美另类女人| 久久久久久有精品国产| 亚洲国产天堂久久综合| 欧美日韩在线播放三区| 久久精品夜色噜噜亚洲aⅴ| 久久最新视频| 欧美色区777第一页| 欧美 日韩 国产精品免费观看| 欧美日韩国产小视频在线观看| 免费永久网站黄欧美| 国产日产欧美a一级在线| 亚洲精品之草原avav久久| 在线欧美影院| 久久精品国产综合精品| 午夜久久久久久久久久一区二区| 欧美精品 国产精品| 欧美激情久久久久久| 国产人久久人人人人爽| 中日韩美女免费视频网站在线观看| 99精品热6080yy久久| 亚洲免费福利视频| 久久免费高清视频| 蜜桃精品一区二区三区| 1024成人| 欧美电影免费观看高清| 欧美国产在线视频| 91久久线看在观草草青青| 欧美xx视频| 91久久精品国产91性色| 狠狠色丁香久久婷婷综合丁香| 国产伦精品一区二区三| 国产精品久久777777毛茸茸| 欧美日韩视频在线| 欧美性大战久久久久久久| 国产精品v欧美精品∨日韩| 欧美激情中文不卡| 亚洲一区二区三区免费在线观看 | 国产精品日本| 欧美成人黑人xx视频免费观看| 久热精品视频在线观看一区| 久久人91精品久久久久久不卡| 中文国产一区| 在线视频亚洲一区| 一区二区三区精品国产| 亚洲卡通欧美制服中文| 一区二区高清视频在线观看| 日韩一级不卡| 欧美成人四级电影| 亚洲欧美一区二区三区极速播放| 欧美在线播放视频| 欧美理论电影网| 久久久久久久综合色一本| 美女露胸一区二区三区| 亚洲精品国产视频| 国产精品理论片| 欧美在线亚洲一区| 亚洲成在人线av| 99在线精品视频| 国产日韩精品入口| 美女精品在线| 久久精品人人做人人爽| 在线精品观看| 亚洲最黄网站| 另类酷文…触手系列精品集v1小说| 欧美成人a视频| 在线日韩视频| 欧美在线视频全部完| 国产美女精品人人做人人爽| 久久国产精品一区二区三区| 久久久久免费视频| 性欧美精品高清| 国产日韩精品一区| 欧美一二三视频| 亚洲在线一区| 中文无字幕一区二区三区| 国产精品尤物| 亚洲三级影片| 欧美日韩直播| 久久午夜精品一区二区| 这里只有精品视频在线| 欧美精品一区三区| 亚洲经典三级| 国产农村妇女精品一区二区 | 亚洲狼人精品一区二区三区| 久久亚洲综合色一区二区三区|